From b1cd23459ee316ab126ad66a4fc4c4186cecdfd2 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 29 Jan 2019 11:31:26 +0800 Subject: [PATCH] feat : add kubeserviceDiscovery test --- samples/OelotKube/ApiGateway/ocelot.json | 11 +- .../KubeProvider.cs | 6 +- .../KubeServiceDiscoveryProviderTests.cs | 148 ++++++++++++++++++ test/Ocelot.UnitTests/Ocelot.UnitTests.csproj | 3 +- 4 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs diff --git a/samples/OelotKube/ApiGateway/ocelot.json b/samples/OelotKube/ApiGateway/ocelot.json index 4830a359..eabb960b 100644 --- a/samples/OelotKube/ApiGateway/ocelot.json +++ b/samples/OelotKube/ApiGateway/ocelot.json @@ -3,8 +3,8 @@ { "DownstreamPathTemplate": "/api/values", "DownstreamScheme": "http", - "UpstreamPathTemplate": "/Category", - "ServiceName": "DownstreamService", + "UpstreamPathTemplate": "/values", + "ServiceName": "downstreamservice", "UpstreamHttpMethod": [ "Get" ], "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, @@ -18,9 +18,10 @@ "RequestIdKey": "OcRequestId", "AdministrationPath": "/administration", "ServiceDiscoveryProvider": { - "Host": "localhost", - "Port": 8001, - "Namesapce": "dev", + "Host": "192.168.0.13", + "Port": 443, + "Token": "txpc696iUhbVoudg164r93CxDTrKRVWG", + "Namespace": "dev", "Type": "kube" } } diff --git a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs index eb3a23b2..4492fb09 100644 --- a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs +++ b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs @@ -13,19 +13,19 @@ namespace Ocelot.Provider.Kubernetes public class Kube : IServiceDiscoveryProvider { private KubeRegistryConfiguration kubeRegistryConfiguration; - private IOcelotLoggerFactory factory; + private IOcelotLogger logger; private IKubeApiClient kubeApi; - private IKubeApiClientFactory kubeClientFactory; public Kube(KubeRegistryConfiguration kubeRegistryConfiguration, IOcelotLoggerFactory factory, IKubeApiClientFactory kubeClientFactory) { this.kubeRegistryConfiguration = kubeRegistryConfiguration; - this.factory = factory; + this.logger = factory.CreateLogger(); this.kubeApi = kubeClientFactory.Get(kubeRegistryConfiguration); } public async Task> Get() { + logger.LogDebug($"namespace:{kubeRegistryConfiguration.KubeNamespace } service:{kubeRegistryConfiguration.KeyOfServiceInK8s}"); var service = await kubeApi.ServicesV1().Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); var services = new List(); if (IsValid(service)) diff --git a/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs new file mode 100644 index 00000000..bf4bab80 --- /dev/null +++ b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs @@ -0,0 +1,148 @@ +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 System.Text; +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 _services; + private readonly Mock _factory; + private readonly Mock _logger; + private string _receivedToken; + private readonly IKubeApiClientFactory _clientFactory; + + public KubeServiceDiscoveryProviderTests() + { + _serviceName = "test"; + _namespaces = "dev"; + _port = 8500; + _kubeHost = "localhost"; + _fakekubeServiceDiscoveryUrl = $"https://{_kubeHost}:{_port}"; + _serviceEntries = new ServiceV1(); + _factory = new Mock(); + _clientFactory = new KubeApiClientFactory(); + _logger = new Mock(); + _factory.Setup(x => x.CreateLogger()).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(); + } + } +} diff --git a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj index 67c264e8..ae11a695 100644 --- a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj +++ b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj @@ -20,6 +20,7 @@ + @@ -72,7 +73,7 @@ - +