private async Task AddIngressTriggersAsync()

in src/routingmanager/RoutingManagerApp.cs [280:393]


        private async Task AddIngressTriggersAsync(
            ConcurrentDictionary<V1Service, RoutingStateEstablisherInput> routingStateEstablisherInputMap,
            IEnumerable<V1Ingress> userIngresses,
            IEnumerable<V1Service> userServices,
            IEnumerable<V1Pod> pods,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            foreach (var ingress in userIngresses)
            {
                _log.Info("Processing the ingress named '{0}'", new PII(ingress.Metadata.Name));
                if (string.IsNullOrWhiteSpace(ingress?.Metadata?.Name) || string.IsNullOrWhiteSpace(ingress?.Metadata?.NamespaceProperty))
                {
                    _log.Warning("Encountered ingress with null/empty name or namespace property");
                    continue;
                }

                var isAgicIngress = ingress.IsAgicIngress();
                _log.Verbose("Is Agic ingress: {0}", isAgicIngress);
                _log.Verbose("Agic backend hostname found : '{0}'", ingress.TryGetAgicBackendHostnameAnnotation(_log, out string agicBackendHostnameAnnotationValue));

                var rules = ingress.Spec?.Rules;
                if (rules == null)
                {
                    // Nothing to do
                    _log.Warning("No rules for ingress '{0}' in namespace '{1}'", new PII(ingress.Metadata.Name), new PII(ingress.Metadata.NamespaceProperty));
                    continue;
                }
                if (rules.Any(rule => !string.IsNullOrEmpty(rule.Host) && rule.Http?.Paths != null && rule.Http.Paths.Any(path => !string.IsNullOrEmpty(path.Path) && path.Path.Contains(Common.Constants.Https.AcmePath))))
                {
                    // https://letsencrypt.org/docs/challenge-types/
                    _log.Verbose("Ignoring this ingress since it is an ACME HTTP01 challenge ingress");
                    continue;
                }

                (var httpReadinessProbe, var httpLivenessProbe) = await GetHttpProbesRunningUnderIngressAsync(ingress, userServices, pods, cancellationToken);

                foreach (var rule in rules)
                {
                    var paths = rule.Http?.Paths;
                    if (paths == null)
                    {
                        // Nothing to do
                        _log.Warning("No paths on rule for ingress '{0}' in namespace '{1}'", new PII(ingress.Metadata.Name), new PII(ingress.Metadata.NamespaceProperty));
                        continue;
                    }
                    foreach (var path in paths)
                    {
                        var serviceName = path?.Backend?.Service?.Name;
                        string servicePort = path?.Backend?.Service?.Port?.Name;
                        if (string.IsNullOrEmpty(servicePort)) {
                            servicePort = path?.Backend?.Service?.Port?.Number.ToString();
                            _log.Info("service port name not found for ingress, port number is {0}", servicePort);
                        }
                        if (!string.IsNullOrWhiteSpace(serviceName))
                        {
                            V1Service serviceToAdd;
                            if ((serviceToAdd = userServices.FirstOrDefault(svc => StringComparer.OrdinalIgnoreCase.Equals(svc.Metadata.Name, serviceName))) == default(V1Service))
                            {
                                //  If we do not find the service in the same namespace, this ingress is broken.
                                _log.Warning("Service '{0}' was not found which was expected to be trigger service. Skipping this ingress trigger named '{1}' with host '{2}' since it is invalid.",
                                    new PII(serviceName), new PII(ingress.Metadata.Name), new PII(rule.Host ?? string.Empty));
                                continue;
                            }

                            string serviceProtocol;
                            int servicePort_int;
                            try
                            {
                                (serviceProtocol, servicePort_int) = await GetProtocolAndPortNumberFromServiceNamedPort(serviceToAdd, servicePort, ingress.Metadata.Name, cancellationToken);
                            }
                            catch (InvalidOperationException)
                            {
                                _log.Error("Unable to retrieve the integer port for the named port '{0}' for service '{1}' in ingress '{2}'. Ignoring corresponding ingress trigger with host '{3}'",
                                    new PII(servicePort), new PII(serviceName), new PII(ingress.Metadata.Name), new PII(string.IsNullOrWhiteSpace(rule.Host) ? string.Empty : rule.Host));
                                continue;
                            }
                            catch (RoutingException)
                            {
                                _log.Info("Ignoring service path '{0}' in ingress '{1}'", new PII(path.Backend.Service.Name), new PII(ingress.Metadata.Name));
                                continue;
                            }

                            if (!StringComparer.OrdinalIgnoreCase.Equals(serviceProtocol, KubernetesConstants.Protocols.Tcp))
                            {
                                _log.Error("Detected service protocol '{0}'. Routing manager does not support protocols other than TCP. Ignoring corresponding ingress trigger named '{1}' with host '{2}'",
                                    serviceProtocol, new PII(ingress.Metadata.Name), new PII(string.IsNullOrWhiteSpace(rule.Host) ? string.Empty : rule.Host));
                                continue;
                            }

                            if (!await ReplaceServiceNamedPortsAsync(serviceToAdd, pods, cancellationToken))
                            {
                                _log.Warning("'{0}' Trigger service's underlying pods or pod's corresponding port was not found in order to resolve named target port. Ignoring corresponding ingress trigger named '{1}'",
                                        new PII(serviceToAdd.Metadata.Name), new PII(ingress.Metadata.Name));
                                continue;
                            }

                            var ingressTriggerToAdd =
                                new IngressTriggerConfig(
                                    namespaceName: ingress.Metadata.NamespaceProperty,
                                    triggerService: serviceToAdd,
                                    ingressName: ingress.Metadata.Name,
                                    servicePort: servicePort_int,
                                    host: rule.Host,
                                    isAgicIngress: isAgicIngress,
                                    agicBackendHostname: agicBackendHostnameAnnotationValue,
                                    httpReadinessProbe: httpReadinessProbe,
                                    httpLivenessProbe: httpLivenessProbe);
                            routingStateEstablisherInputMap.AddOrUpdateWithTrigger(serviceToAdd, ingressTriggerToAdd);
                        }
                    }
                }
            }
        }