in pkg/appgw/istio_settings.go [51:183]
func (c *appGwConfigBuilder) getIstioDestinationsAndSettingsMap(cbCtx *ConfigBuilderContext) ([]n.ApplicationGatewayBackendHTTPSettings, map[istioDestinationIdentifier]*n.ApplicationGatewayBackendHTTPSettings, map[istioDestinationIdentifier]serviceBackendPortPair, error) {
serviceBackendPairsMap := make(map[istioDestinationIdentifier]map[serviceBackendPortPair]interface{})
backendHTTPSettingsMap := make(map[istioDestinationIdentifier]*n.ApplicationGatewayBackendHTTPSettings)
finalServiceBackendPairMap := make(map[istioDestinationIdentifier]serviceBackendPortPair)
var unresolvedDestinationID []istioDestinationIdentifier
_, destinationIDs := istioMatchDestinationIds(cbCtx)
for destinationID := range destinationIDs {
resolvedBackendPorts := make(map[serviceBackendPortPair]interface{})
service := c.k8sContext.GetService(destinationID.serviceKey())
destinationPortNum := Port(destinationID.DestinationPort)
if service == nil {
// Once services are filtered in the istioMatchDestinationIDs function, this should never happen
logLine := fmt.Sprintf("Unable to get the service [%s]", destinationID.serviceKey())
klog.Errorf(logLine)
// TODO(rhea): add error event
pair := serviceBackendPortPair{
ServicePort: Port(destinationPortNum),
BackendPort: Port(destinationPortNum),
}
resolvedBackendPorts[pair] = nil
} else {
for _, sp := range service.Spec.Ports {
// find the backend port number
// check if any service ports matches the specified ports
if sp.Protocol != v1.ProtocolTCP {
// ignore UDP ports
continue
}
// TODO(delqn): implement correctly port lookup by name
if Port(sp.Port) == destinationPortNum || sp.TargetPort.String() == fmt.Sprint(destinationPortNum) {
// matched a service port with a port from the service
if sp.TargetPort.String() == "" {
// targetPort is not defined, by default targetPort == port
pair := serviceBackendPortPair{
ServicePort: Port(sp.Port),
BackendPort: Port(sp.Port),
}
resolvedBackendPorts[pair] = nil
} else {
// target port is defined as name or port number
if sp.TargetPort.Type == intstr.Int {
// port is defined as port number
pair := serviceBackendPortPair{
ServicePort: Port(sp.Port),
BackendPort: Port(sp.TargetPort.IntVal),
}
resolvedBackendPorts[pair] = nil
} else {
// if service port is defined by name, need to resolve
targetPortName := sp.TargetPort.StrVal
klog.V(1).Infof("resolving port name %s", targetPortName)
targetPortsResolved := c.resolveIstioPortName(targetPortName, &destinationID)
for targetPort := range targetPortsResolved {
pair := serviceBackendPortPair{
ServicePort: Port(sp.Port),
BackendPort: Port(targetPort),
}
resolvedBackendPorts[pair] = nil
}
}
}
break
}
}
}
if len(resolvedBackendPorts) == 0 {
logLine := fmt.Sprintf("Unable to resolve any backend port for service [%s]", destinationID.serviceKey())
klog.Error(logLine)
//TODO(rhea): Add error event
unresolvedDestinationID = append(unresolvedDestinationID, destinationID)
break
}
// Merge serviceBackendPairsMap[backendID] into resolvedBackendPorts
if _, ok := serviceBackendPairsMap[destinationID]; !ok {
serviceBackendPairsMap[destinationID] = make(map[serviceBackendPortPair]interface{})
}
for portPair := range resolvedBackendPorts {
serviceBackendPairsMap[destinationID][portPair] = nil
}
}
if len(unresolvedDestinationID) > 0 {
e := controllererrors.NewError(
controllererrors.ErrorIstioResolvePortsForServices,
"unable to resolve backend port for some services",
)
return nil, nil, nil, e
}
httpSettingsCollection := make(map[string]n.ApplicationGatewayBackendHTTPSettings)
for destinationID, serviceBackendPairs := range serviceBackendPairsMap {
if len(serviceBackendPairs) > 1 {
// more than one possible backend port exposed through ingress
backendServicePort := ""
if destinationID.DestinationPort != 0 {
backendServicePort = fmt.Sprint(destinationID.DestinationPort)
} else {
// TODO(delqn): implement port lookup by name
}
//TODO(rhea): add error event recorder
e := controllererrors.NewErrorf(
controllererrors.ErrorIstioMultipleServiceBackendPortBinding,
"service:port [%s:%s] has more than one service-backend port binding",
destinationID.serviceKey(), backendServicePort,
)
klog.Warning(e.Error())
return nil, nil, nil, e
}
// At this point there will be only one pair
var uniquePair serviceBackendPortPair
for k := range serviceBackendPairs {
uniquePair = k
}
finalServiceBackendPairMap[destinationID] = uniquePair
httpSettings := c.generateIstioHTTPSettings(destinationID, uniquePair.BackendPort, cbCtx)
httpSettingsCollection[*httpSettings.Name] = httpSettings
backendHTTPSettingsMap[destinationID] = &httpSettings
}
httpSettings := make([]n.ApplicationGatewayBackendHTTPSettings, 0, len(httpSettingsCollection))
for _, backend := range httpSettingsCollection {
httpSettings = append(httpSettings, backend)
}
return httpSettings, backendHTTPSettingsMap, finalServiceBackendPairMap, nil
}