Repository: traefik/traefik
File: pkg/provider/kubernetes/ingress/kubernetes.go (Go)

Code before:
				rt.Observability = rtConfig.Router.Observability
			}

			p.applyRouterTransform(ctxIngress, rt, ingress)

			conf.HTTP.Routers["default-router"] = rt
			conf.HTTP.Services["default-backend"] = service
		}

		routers := map[string][]*dynamic.Router{}

		for _, rule := range ingress.Spec.Rules {
			if rule.HTTP == nil {
				continue
			}

			for _, pa := range rule.HTTP.Paths {
				if pa.Backend.Resource != nil {
					// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
					logger.Error().Msg("Resource backends are not supported")
					continue
				}

				service, err := p.loadService(client, ingress.Namespace, pa.Backend)
				if err != nil {
					logger.Error().
						Str("serviceName", pa.Backend.Service.Name).
						Str("servicePort", pa.Backend.Service.Port.String()).
						Err(err).
						Msg("Cannot create service")
					continue
				}

				if len(service.LoadBalancer.Servers) == 0 && !p.AllowEmptyServices {
					logger.Error().
						Str("serviceName", pa.Backend.Service.Name).
						Str("servicePort", pa.Backend.Service.Port.String()).
						Msg("Skipping service: no endpoints found")
					continue
				}

				portString := pa.Backend.Service.Port.Name

				if len(pa.Backend.Service.Port.Name) == 0 {
					portString = strconv.Itoa(int(pa.Backend.Service.Port.Number))
				}

				serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
				conf.HTTP.Services[serviceName] = service

				rt := p.loadRouter(rule, pa, rtConfig, serviceName)

Review comment (suggestion):
Probably still shouldn't assume that pa.Backend.Service is non-nil here, even with the check for pa.Backend.Resource above.

loadService literally checks for `backend.Service == nil` and returns an error, and then the error logger goes and tries to do `backend.Service.Name` which we KNOW is going to cause a panic.

Code after:

			for _, pa := range rule.HTTP.Paths {
				if pa.Backend.Resource != nil {
					// https://kubernetes.io/docs/concepts/services-networking/ingress/#resource-backend
					log.FromContext(ctxIngress).Error("Resource backends are not supported")
					continue
				}

				if pa.Backend.Service == nil {
					log.FromContext(ctxIngress).Error("Missing service definition")
					continue
				}

				service, err := p.loadService(client, ingress.Namespace, pa.Backend)
				if err != nil {
					log.FromContext(ctxIngress).
						WithField("serviceName", pa.Backend.Service.Name).
						WithField("servicePort", pa.Backend.Service.Port.String()).
						Errorf("Cannot create service: %v", err)
					continue
				}

				if len(service.LoadBalancer.Servers) == 0 && !p.AllowEmptyServices {
					log.FromContext(ctxIngress).
						WithField("serviceName", pa.Backend.Service.Name).
						WithField("servicePort", pa.Backend.Service.Port.String()).
						Errorf("Skipping service: no endpoints found")
					continue
				}

				portString := pa.Backend.Service.Port.Name

				if len(pa.Backend.Service.Port.Name) == 0 {
					portString = strconv.Itoa(int(pa.Backend.Service.Port.Number))
				}

				serviceName := provider.Normalize(ingress.Namespace + "-" + pa.Backend.Service.Name + "-" + portString)
				conf.HTTP.Services[serviceName] = service

				rt := loadRouter(rule, pa, rtConfig, serviceName)

				p.applyRouterTransform(ctxIngress, rt, ingress)

				routerKey := strings.TrimPrefix(provider.Normalize(ingress.Namespace+"-"+ingress.Name+"-"+rule.Host+pa.Path), "-")

				routers[routerKey] = append(routers[routerKey], rt)
			}
		}

		for routerKey, conflictingRouters := range routers {
			if len(conflictingRouters) == 1 {