mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 20:30:50 +08:00 
			
		
		
		
	kubernetes provider (#772)
* feat: Kubernetes ServiceDiscoveryProvider * 编写k8s测试例子 * feat:fix kube config * feat: remove port * feat : complete the k8s test * feat : add kubeserviceDiscovery test * feat : add kube provider unittest * feat :add kubetnetes docs how to use ocelot with kubetnetes docs * keep the configuration as simple as possible, no qos, no cache * fix: use http * add PollingKubeServiceDiscovery * feat : refactor logger * feat : add pollkube docs * feat:Remove unnecessary code * feat : code-block json
This commit is contained in:
		
				
					committed by
					
						
						Marcelo Castagna
					
				
			
			
				
	
			
			
			
						parent
						
							05ede70e62
						
					
				
				
					commit
					44dccf1fce
				
			
							
								
								
									
										35
									
								
								test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Provider.Kubernetes;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using System;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Kubernetes
 | 
			
		||||
{
 | 
			
		||||
    public class KubeProviderFactoryTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceProvider _provider;
 | 
			
		||||
 | 
			
		||||
        public KubeProviderFactoryTests()
 | 
			
		||||
        {
 | 
			
		||||
            var services = new ServiceCollection();
 | 
			
		||||
            var loggerFactory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            var logger = new Mock<IOcelotLogger>();
 | 
			
		||||
            loggerFactory.Setup(x => x.CreateLogger<Kube>()).Returns(logger.Object);
 | 
			
		||||
            var kubeFactory = new Mock<IKubeApiClientFactory>();
 | 
			
		||||
            services.AddSingleton(kubeFactory.Object);
 | 
			
		||||
            services.AddSingleton(loggerFactory.Object);
 | 
			
		||||
            _provider = services.BuildServiceProvider();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_KubeServiceDiscoveryProvider()
 | 
			
		||||
        {
 | 
			
		||||
            var provider = KubernetesProviderFactory.Get(_provider, new ServiceProviderConfiguration("kube", "localhost", 443, "", "", 1,"dev"), "");
 | 
			
		||||
            provider.ShouldBeOfType<Kube>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,147 @@
 | 
			
		||||
using KubeClient.Models;
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Moq;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Provider.Kubernetes;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Kubernetes
 | 
			
		||||
{
 | 
			
		||||
    public class KubeServiceDiscoveryProviderTests : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        private IWebHost _fakeKubeBuilder;
 | 
			
		||||
        private ServiceV1 _serviceEntries;
 | 
			
		||||
        private Kube _provider;
 | 
			
		||||
        private readonly string _serviceName;
 | 
			
		||||
        private readonly string _namespaces;
 | 
			
		||||
        private readonly int _port;
 | 
			
		||||
        private readonly string _kubeHost;
 | 
			
		||||
        private readonly string _fakekubeServiceDiscoveryUrl;
 | 
			
		||||
        private List<Service> _services;
 | 
			
		||||
        private readonly Mock<IOcelotLoggerFactory> _factory;
 | 
			
		||||
        private readonly Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private string _receivedToken;
 | 
			
		||||
        private readonly IKubeApiClientFactory _clientFactory;
 | 
			
		||||
 | 
			
		||||
        public KubeServiceDiscoveryProviderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _serviceName = "test";
 | 
			
		||||
            _namespaces = "dev";
 | 
			
		||||
            _port = 8001;
 | 
			
		||||
            _kubeHost = "localhost";
 | 
			
		||||
            _fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}";
 | 
			
		||||
            _serviceEntries = new ServiceV1();
 | 
			
		||||
            _factory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            _clientFactory = new KubeApiClientFactory();
 | 
			
		||||
            _logger = new Mock<IOcelotLogger>();
 | 
			
		||||
            _factory.Setup(x => x.CreateLogger<Kube>()).Returns(_logger.Object);
 | 
			
		||||
            var config = new KubeRegistryConfiguration()
 | 
			
		||||
            {
 | 
			
		||||
                ApiEndPoint = new Uri(_fakekubeServiceDiscoveryUrl),
 | 
			
		||||
                AccessToken = "txpc696iUhbVoudg164r93CxDTrKRVWG",
 | 
			
		||||
                AllowInsecure = true,
 | 
			
		||||
                AuthStrategy = KubeClient.KubeAuthStrategy.BearerToken,
 | 
			
		||||
                KeyOfServiceInK8s = _serviceName,
 | 
			
		||||
                KubeNamespace = _namespaces
 | 
			
		||||
            };
 | 
			
		||||
            _provider = new Kube(config, _factory.Object, _clientFactory);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_service_from_k8s()
 | 
			
		||||
        {
 | 
			
		||||
            var token = "Bearer txpc696iUhbVoudg164r93CxDTrKRVWG";
 | 
			
		||||
            var serviceEntryOne = new ServiceV1()
 | 
			
		||||
            {
 | 
			
		||||
                Kind = "service",
 | 
			
		||||
                ApiVersion = "1.0",
 | 
			
		||||
                Metadata = new ObjectMetaV1()
 | 
			
		||||
                {
 | 
			
		||||
                    Namespace = "dev"
 | 
			
		||||
                },
 | 
			
		||||
                Spec = new ServiceSpecV1()
 | 
			
		||||
                 {
 | 
			
		||||
                     ClusterIP = "localhost"                     
 | 
			
		||||
                },
 | 
			
		||||
                Status = new ServiceStatusV1() {
 | 
			
		||||
                    LoadBalancer = new LoadBalancerStatusV1()
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            serviceEntryOne.Spec.Ports.Add(
 | 
			
		||||
                new ServicePortV1()
 | 
			
		||||
                {
 | 
			
		||||
                    Port = 80
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenThereIsAFakeKubeServiceDiscoveryProvider(_fakekubeServiceDiscoveryUrl,  _serviceName, _namespaces))
 | 
			
		||||
                .And(x => GivenTheServicesAreRegisteredWithKube(serviceEntryOne))
 | 
			
		||||
                .When(x => WhenIGetTheServices())
 | 
			
		||||
                .Then(x => ThenTheCountIs(1))
 | 
			
		||||
                .And(_ => _receivedToken.ShouldBe(token))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheCountIs(int count)
 | 
			
		||||
        {
 | 
			
		||||
            _services.Count.ShouldBe(count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheServices()
 | 
			
		||||
        {
 | 
			
		||||
            _services = _provider.Get().GetAwaiter().GetResult();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenTheServicesAreRegisteredWithKube(ServiceV1 serviceEntries)
 | 
			
		||||
        {
 | 
			
		||||
            _serviceEntries = serviceEntries;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private void GivenThereIsAFakeKubeServiceDiscoveryProvider(string url, string serviceName, string namespaces)
 | 
			
		||||
        {
 | 
			
		||||
            _fakeKubeBuilder = new WebHostBuilder()
 | 
			
		||||
                .UseUrls(url)
 | 
			
		||||
                .UseKestrel()
 | 
			
		||||
                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
			
		||||
                .UseIISIntegration()
 | 
			
		||||
                .UseUrls(url)
 | 
			
		||||
                .Configure(app =>
 | 
			
		||||
                {
 | 
			
		||||
                    app.Run(async context =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (context.Request.Path.Value == $"/api/v1/namespaces/{namespaces}/services/{serviceName}")
 | 
			
		||||
                        {
 | 
			
		||||
                            if (context.Request.Headers.TryGetValue("Authorization", out var values))
 | 
			
		||||
                            {
 | 
			
		||||
                                _receivedToken = values.First();
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            var json = JsonConvert.SerializeObject(_serviceEntries);
 | 
			
		||||
                            context.Response.Headers.Add("Content-Type", "application/json");
 | 
			
		||||
                            await context.Response.WriteAsync(json);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                })
 | 
			
		||||
                .Build();
 | 
			
		||||
 | 
			
		||||
            _fakeKubeBuilder.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
        {
 | 
			
		||||
            _fakeKubeBuilder?.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,70 @@
 | 
			
		||||
using Microsoft.AspNetCore.Hosting;
 | 
			
		||||
using Microsoft.AspNetCore.Hosting.Internal;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Ocelot.DependencyInjection;
 | 
			
		||||
using Ocelot.Provider.Kubernetes;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Kubernetes
 | 
			
		||||
{
 | 
			
		||||
    public class OcelotBuilderExtensionsTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IServiceCollection _services;
 | 
			
		||||
        private IServiceProvider _serviceProvider;
 | 
			
		||||
        private readonly IConfiguration _configRoot;
 | 
			
		||||
        private IOcelotBuilder _ocelotBuilder;
 | 
			
		||||
        private Exception _ex;
 | 
			
		||||
 | 
			
		||||
        public OcelotBuilderExtensionsTests()
 | 
			
		||||
        {
 | 
			
		||||
            _configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
 | 
			
		||||
            _services = new ServiceCollection();
 | 
			
		||||
            _services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
 | 
			
		||||
            _services.AddSingleton(_configRoot);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_set_up_kubernetes()
 | 
			
		||||
        {
 | 
			
		||||
            this.Given(x => WhenISetUpOcelotServices())
 | 
			
		||||
                .When(x => WhenISetUpKubernetes())
 | 
			
		||||
                .Then(x => ThenAnExceptionIsntThrown())
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpOcelotServices()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder = _services.AddOcelot(_configRoot);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenISetUpKubernetes()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                _ocelotBuilder.AddKubernetes();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                _ex = e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenAnExceptionIsntThrown()
 | 
			
		||||
        {
 | 
			
		||||
            _ex.ShouldBeNull();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,82 @@
 | 
			
		||||
using Moq;
 | 
			
		||||
using Ocelot.Infrastructure;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Provider.Kubernetes;
 | 
			
		||||
using Ocelot.ServiceDiscovery.Providers;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
using Shouldly;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using TestStack.BDDfy;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.UnitTests.Kubernetes
 | 
			
		||||
{
 | 
			
		||||
    public class PollingKubeServiceDiscoveryProviderTests
 | 
			
		||||
    {
 | 
			
		||||
        private readonly int _delay;
 | 
			
		||||
        private PollKube _provider;
 | 
			
		||||
        private readonly List<Service> _services;
 | 
			
		||||
        private readonly Mock<IOcelotLoggerFactory> _factory;
 | 
			
		||||
        private readonly Mock<IOcelotLogger> _logger;
 | 
			
		||||
        private readonly Mock<IServiceDiscoveryProvider> _kubeServiceDiscoveryProvider;
 | 
			
		||||
        private List<Service> _result;
 | 
			
		||||
 | 
			
		||||
        public PollingKubeServiceDiscoveryProviderTests()
 | 
			
		||||
        {
 | 
			
		||||
            _services = new List<Service>();
 | 
			
		||||
            _delay = 1;
 | 
			
		||||
            _factory = new Mock<IOcelotLoggerFactory>();
 | 
			
		||||
            _logger = new Mock<IOcelotLogger>();
 | 
			
		||||
            _factory.Setup(x => x.CreateLogger<PollKube>()).Returns(_logger.Object);
 | 
			
		||||
            _kubeServiceDiscoveryProvider = new Mock<IServiceDiscoveryProvider>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void should_return_service_from_kube()
 | 
			
		||||
        {
 | 
			
		||||
            var service = new Service("", new ServiceHostAndPort("", 0), "", "", new List<string>());
 | 
			
		||||
 | 
			
		||||
            this.Given(x => GivenKubeReturns(service))
 | 
			
		||||
                .When(x => WhenIGetTheServices(1))
 | 
			
		||||
                .Then(x => ThenTheCountIs(1))
 | 
			
		||||
                .BDDfy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void GivenKubeReturns(Service service)
 | 
			
		||||
        {
 | 
			
		||||
            _services.Add(service);
 | 
			
		||||
            _kubeServiceDiscoveryProvider.Setup(x => x.Get()).ReturnsAsync(_services);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void ThenTheCountIs(int count)
 | 
			
		||||
        {
 | 
			
		||||
            _result.Count.ShouldBe(count);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void WhenIGetTheServices(int expected)
 | 
			
		||||
        {
 | 
			
		||||
            _provider = new PollKube(_delay, _factory.Object, _kubeServiceDiscoveryProvider.Object);
 | 
			
		||||
 | 
			
		||||
            var result = Wait.WaitFor(3000).Until(() => {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    _result = _provider.Get().GetAwaiter().GetResult();
 | 
			
		||||
                    if (_result.Count == expected)
 | 
			
		||||
                    {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception)
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            result.ShouldBeTrue();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user