Example #1
0
    public async Task ProcessAsync(CancellationToken cancellationToken)
    {
        try
        {
            var ingresses = _cache.GetIngresses().ToArray();

            var configContext = new YarpConfigContext();

            foreach (var ingress in ingresses)
            {
                if (_cache.TryGetReconcileData(new NamespacedName(ingress.Metadata.NamespaceProperty, ingress.Metadata.Name), out var data))
                {
                    var ingressContext = new YarpIngressContext(ingress, data.ServiceList, data.EndpointsList);
                    YarpParser.ConvertFromKubernetesIngress(ingressContext, configContext);
                }
            }

            var clusters = configContext.BuildClusterConfig();

            _logger.LogInformation(JsonSerializer.Serialize(configContext.Routes));
            _logger.LogInformation(JsonSerializer.Serialize(clusters));

            await _updateConfig.UpdateAsync(configContext.Routes, clusters, cancellationToken).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Uncaught exception occured while reconciling");
            throw;
        }
    }
Example #2
0
    public async Task ParsingTests(string name)
    {
        var cache = await GetKubernetesInfo(name).ConfigureAwait(false);

        var configContext = new YarpConfigContext();
        var ingresses     = cache.GetIngresses().ToArray();

        foreach (var ingress in ingresses)
        {
            if (cache.TryGetReconcileData(new NamespacedName(ingress.Metadata.NamespaceProperty, ingress.Metadata.Name), out var data))
            {
                var ingressContext = new YarpIngressContext(ingress, data.ServiceList, data.EndpointsList);
                YarpParser.ConvertFromKubernetesIngress(ingressContext, configContext);
            }
        }

        VerifyClusters(JsonSerializer.Serialize(configContext.BuildClusterConfig()), name);
        VerifyRoutes(JsonSerializer.Serialize(configContext.Routes), name);
    }
Example #3
0
    public async Task ProcessAsync(CancellationToken cancellationToken)
    {
        try
        {
            var ingresses = _cache.GetIngresses().ToArray();

            var message = new Message
            {
                MessageType = MessageType.Update,
                Key         = string.Empty,
            };

            var configContext = new YarpConfigContext();

            foreach (var ingress in ingresses)
            {
                if (_cache.TryGetReconcileData(new NamespacedName(ingress.Metadata.NamespaceProperty, ingress.Metadata.Name), out var data))
                {
                    var ingressContext = new YarpIngressContext(ingress, data.ServiceList, data.EndpointsList);
                    YarpParser.ConvertFromKubernetesIngress(ingressContext, configContext);
                }
            }

            message.Cluster = configContext.BuildClusterConfig();
            message.Routes  = configContext.Routes;

            var bytes = JsonSerializer.SerializeToUtf8Bytes(message);

            _logger.LogInformation(JsonSerializer.Serialize(message));

            await _dispatcher.SendAsync(null, bytes, cancellationToken).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex.Message);
            throw;
        }
    }
    public async Task ParsingTests(string name)
    {
        var ingressClass = KubeResourceGenerator.CreateIngressClass("yarp", "microsoft.com/ingress-yarp", true);
        var cache        = await GetKubernetesInfo(name, ingressClass).ConfigureAwait(false);

        var configContext = new YarpConfigContext();
        var ingresses     = cache.GetIngresses().ToArray();

        foreach (var ingress in ingresses)
        {
            if (cache.TryGetReconcileData(new NamespacedName(ingress.Metadata.NamespaceProperty, ingress.Metadata.Name), out var data))
            {
                var ingressContext = new YarpIngressContext(ingress, data.ServiceList, data.EndpointsList);
                YarpParser.ConvertFromKubernetesIngress(ingressContext, configContext);
            }
        }
        var options = new JsonSerializerOptions {
            Converters = { new JsonStringEnumConverter() }
        };

        VerifyClusters(JsonSerializer.Serialize(configContext.BuildClusterConfig(), options), name);
        VerifyRoutes(JsonSerializer.Serialize(configContext.Routes, options), name);
    }
Example #5
0
    private static void HandleIngressRulePath(YarpIngressContext ingressContext, V1ServicePort servicePort, List <Endpoints> endpoints, IList <V1EndpointSubset> defaultSubsets, V1IngressRule rule, V1HTTPIngressPath path, YarpConfigContext configContext)
    {
        var backend = path.Backend;
        var ingressServiceBackend = backend.Service;
        var subsets = defaultSubsets;

        var clusters = configContext.ClusterTransfers;
        var routes   = configContext.Routes;

        if (!string.IsNullOrEmpty(ingressServiceBackend?.Name))
        {
            subsets = endpoints.SingleOrDefault(x => x.Name == ingressServiceBackend?.Name).Subsets;
        }

        // Each ingress rule path can only be for one service
        var key = ingressServiceBackend.Port.Number.HasValue ? $"{ingressServiceBackend?.Name}:{ingressServiceBackend?.Port.Number}" : $"{ingressServiceBackend?.Name}:{ingressServiceBackend?.Port.Name}";

        if (!clusters.ContainsKey(key))
        {
            clusters.Add(key, new ClusterTransfer());
        }

        var cluster = clusters[key];

        cluster.ClusterId = key;

        // make sure cluster is present
        foreach (var subset in subsets ?? Enumerable.Empty <V1EndpointSubset>())
        {
            foreach (var port in subset.Ports ?? Enumerable.Empty <V1EndpointPort>())
            {
                if (!MatchesPort(port, servicePort.TargetPort))
                {
                    continue;
                }

                var pathMatch = FixupPathMatch(path);
                var host      = rule.Host;

                routes.Add(new RouteConfig()
                {
                    Match = new RouteMatch()
                    {
                        Hosts = host != null ? new[] { host } : Array.Empty <string>(),
                        Path  = pathMatch
                    },
                    ClusterId = cluster.ClusterId,
                    RouteId   = $"{ingressContext.Ingress.Metadata.Name}:{path.Path}"
                });

                // Add destination for every endpoint address
                foreach (var address in subset.Addresses ?? Enumerable.Empty <V1EndpointAddress>())
                {
                    var protocol = ingressContext.Options.Https ? "https" : "http";
                    var uri      = $"{protocol}://{address.Ip}:{port.Port}";
                    cluster.Destinations[uri] = new DestinationConfig()
                    {
                        Address = uri
                    };
                }
            }
        }
    }
Example #6
0
    private static void HandleIngressRule(YarpIngressContext ingressContext, List <Endpoints> endpoints, IList <V1EndpointSubset> defaultSubsets, V1IngressRule rule, YarpConfigContext configContext)
    {
        var http = rule.Http;

        foreach (var path in http.Paths ?? Enumerable.Empty <V1HTTPIngressPath>())
        {
            var service     = ingressContext.Services.SingleOrDefault(s => s.Metadata.Name == path.Backend.Service.Name);
            var servicePort = service.Spec.Ports.SingleOrDefault(p => MatchesPort(p, path.Backend.Service.Port));
            HandleIngressRulePath(ingressContext, servicePort, endpoints, defaultSubsets, rule, path, configContext);
        }
    }
Example #7
0
    internal static void ConvertFromKubernetesIngress(YarpIngressContext ingressContext, YarpConfigContext configContext)
    {
        var spec           = ingressContext.Ingress.Spec;
        var defaultBackend = spec?.DefaultBackend;
        var defaultService = defaultBackend?.Service;
        IList <V1EndpointSubset> defaultSubsets = default;

        if (!string.IsNullOrEmpty(defaultService?.Name))
        {
            defaultSubsets = ingressContext.Endpoints.SingleOrDefault(x => x.Name == defaultService?.Name).Subsets;
        }

        // cluster can contain multiple replicas for each destination, need to know the lookup base don endpoints
        var options = HandleAnnotations(ingressContext, ingressContext.Ingress.Metadata);

        foreach (var rule in spec.Rules ?? Enumerable.Empty <V1IngressRule>())
        {
            HandleIngressRule(ingressContext, ingressContext.Endpoints, defaultSubsets, rule, configContext);
        }
    }