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);
}
}
}
}
}