func()

in pkg/appgw/backendhttpsettings.go [112:223]


func (c *appGwConfigBuilder) resolveBackendPort(backendID backendIdentifier) (Port, error) {
	var e error
	service := c.k8sContext.GetService(backendID.serviceKey())
	if service == nil {
		// This should never happen since newBackendIdsFiltered() already filters out backends for non-existent Services
		e = controllererrors.NewErrorf(
			controllererrors.ErrorServiceNotFound,
			"Service not found %s",
			backendID.serviceKey())

		backendPort := Port(80)
		if backendID.Backend.Service.Port.Name == "" && backendID.Backend.Service.Port.Number < 65536 {
			backendPort = Port(backendID.Backend.Service.Port.Number)
		}

		return backendPort, e
	}

	// find the target port number for service port specified in the ingress manifest
	servicePortInIngress := fmt.Sprint(backendID.Backend.Service.Port.Number)
	if backendID.Backend.Service.Port.Name != "" {
		servicePortInIngress = fmt.Sprint(backendID.Backend.Service.Port.Name)
	}

	resolvedBackendPorts := make(map[serviceBackendPortPair]interface{})
	for _, servicePort := range service.Spec.Ports {
		// ignore UDP ports
		if servicePort.Protocol != v1.ProtocolTCP {
			continue
		}

		// match service by either port, port name or target port
		if fmt.Sprint(servicePort.Port) != servicePortInIngress &&
			servicePort.Name != servicePortInIngress &&
			servicePort.TargetPort.String() != servicePortInIngress {
			continue
		}

		// if target port is not specified, use the service port as backend port
		if servicePort.TargetPort.String() == "" {
			// targetPort is not defined, by default targetPort == port
			pair := serviceBackendPortPair{
				ServicePort: Port(servicePort.Port),
				BackendPort: Port(servicePort.Port),
			}
			resolvedBackendPorts[pair] = nil
			continue
		}

		// if target port is an int, use it as backend port
		if servicePort.TargetPort.Type == intstr.Int {
			// port is defined as port number
			pair := serviceBackendPortPair{
				ServicePort: Port(servicePort.Port),
				BackendPort: Port(servicePort.TargetPort.IntVal),
			}
			resolvedBackendPorts[pair] = nil
			continue
		}

		// if target port is port name, then resolve the port number for the port name
		// k8s matches service port name against endpoints port name retrieved by passing backendID service key to endpoint api.
		klog.V(3).Infof("resolving port name '%s' for service '%s' and service port '%s' for Ingress '%s'", servicePort.Name, backendID.serviceKey(), serviceBackendPortToStr(backendID.Backend.Service.Port), backendID.Ingress.Name)
		targetPortsResolved := c.resolvePortName(servicePort.Name, &backendID)
		for targetPort := range targetPortsResolved {
			pair := serviceBackendPortPair{
				ServicePort: Port(servicePort.Port),
				BackendPort: Port(targetPort),
			}
			resolvedBackendPorts[pair] = nil
		}
	}

	backendPort := Port(65536)
	if len(resolvedBackendPorts) == 0 {
		e = controllererrors.NewErrorf(
			controllererrors.ErrorUnableToResolveBackendPortFromServicePort,
			"No port matched %s",
			backendID.serviceKey())
		if backendID.Backend.Service.Port.Name == "" {
			backendPort = Port(backendID.Backend.Service.Port.Number)
		}
	} else {
		var ports []string
		for k := range resolvedBackendPorts {
			ports = append(ports, string(k.BackendPort))
			if k.BackendPort <= backendPort {
				backendPort = k.BackendPort
			}
		}

		if len(resolvedBackendPorts) > 1 {
			// found more than 1 backend port for the service port which is a conflicting scenario
			e = controllererrors.NewErrorf(
				controllererrors.ErrorMultipleServiceBackendPortBinding,
				"service %s and service port %s has more than one service-backend port binding which is not an ideal scenario, choosing the smallest service-backend port %d. Ports found %s.",
				backendID.serviceKey(), serviceBackendPortToStr(backendID.Backend.Service.Port), backendPort, strings.Join(ports, ","),
			)
		}
	}

	if backendPort >= Port(65536) {
		e = controllererrors.NewErrorf(
			controllererrors.ErrorServiceResolvedToInvalidPort,
			"service %s and service port %s was resolved to an invalid service-backend port %d, defaulting to port 80",
			backendID.serviceKey(), serviceBackendPortToStr(backendID.Backend.Service.Port), backendPort,
		)
		backendPort = Port(80)
	}

	return backendPort, e
}