From 3525fda8ade2aabdab96a08eaa858d2a3fd54ede Mon Sep 17 00:00:00 2001 From: geffzhang Date: Sun, 13 Jan 2019 19:23:12 +0800 Subject: [PATCH 01/19] feat: Kubernetes ServiceDiscoveryProvider --- Ocelot.sln | 7 +++ .../IKubeApiClientFactory.cs | 12 ++++ .../KubeApiClientFactory.cs | 22 +++++++ .../KubeProvider.cs | 59 +++++++++++++++++++ .../KubeRegistryConfiguration.cs | 22 +++++++ .../KubernetesProviderFactory.cs | 31 ++++++++++ .../Ocelot.Provider.Kubernetes.csproj | 15 +++++ .../OcelotBuilderExtensions.cs | 20 +++++++ .../ServiceProviderConfigurationBuilder.cs | 9 ++- .../ServiceProviderConfigurationCreator.cs | 2 + .../File/FileServiceDiscoveryProvider.cs | 1 + .../ServiceProviderConfiguration.cs | 10 +++- .../ServiceDiscoveryTests.cs | 3 +- .../ServiceProviderCreatorTests.cs | 7 ++- 14 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 src/Ocelot.Provider.Kubernetes/IKubeApiClientFactory.cs create mode 100644 src/Ocelot.Provider.Kubernetes/KubeApiClientFactory.cs create mode 100644 src/Ocelot.Provider.Kubernetes/KubeProvider.cs create mode 100644 src/Ocelot.Provider.Kubernetes/KubeRegistryConfiguration.cs create mode 100644 src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs create mode 100644 src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj create mode 100644 src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs diff --git a/Ocelot.sln b/Ocelot.sln index f4b3aef3..088d7be0 100644 --- a/Ocelot.sln +++ b/Ocelot.sln @@ -56,6 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Rafty", "sr EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Tracing.Butterfly", "src\Ocelot.Tracing.Butterfly\Ocelot.Tracing.Butterfly.csproj", "{6045E23D-669C-4F27-AF8E-8EEE6DB3557F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ocelot.Provider.Kubernetes", "src\Ocelot.Provider.Kubernetes\Ocelot.Provider.Kubernetes.csproj", "{72C8E528-B4F5-45CE-8A06-CD3787364856}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -114,6 +116,10 @@ Global {6045E23D-669C-4F27-AF8E-8EEE6DB3557F}.Debug|Any CPU.Build.0 = Debug|Any CPU {6045E23D-669C-4F27-AF8E-8EEE6DB3557F}.Release|Any CPU.ActiveCfg = Release|Any CPU {6045E23D-669C-4F27-AF8E-8EEE6DB3557F}.Release|Any CPU.Build.0 = Release|Any CPU + {72C8E528-B4F5-45CE-8A06-CD3787364856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72C8E528-B4F5-45CE-8A06-CD3787364856}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72C8E528-B4F5-45CE-8A06-CD3787364856}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72C8E528-B4F5-45CE-8A06-CD3787364856}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -132,6 +138,7 @@ Global {1F6E5DCF-8A2E-4E24-A25D-064362DE8D0E} = {5CFB79B7-C9DC-45A4-9A75-625D92471702} {AC153C67-EF18-47E6-A230-F0D3CF5F0A98} = {5CFB79B7-C9DC-45A4-9A75-625D92471702} {6045E23D-669C-4F27-AF8E-8EEE6DB3557F} = {5CFB79B7-C9DC-45A4-9A75-625D92471702} + {72C8E528-B4F5-45CE-8A06-CD3787364856} = {5CFB79B7-C9DC-45A4-9A75-625D92471702} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {21476EFF-778A-4F97-8A56-D1AF1CEC0C48} diff --git a/src/Ocelot.Provider.Kubernetes/IKubeApiClientFactory.cs b/src/Ocelot.Provider.Kubernetes/IKubeApiClientFactory.cs new file mode 100644 index 00000000..bd9089d0 --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/IKubeApiClientFactory.cs @@ -0,0 +1,12 @@ +using KubeClient; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ocelot.Provider.Kubernetes +{ + public interface IKubeApiClientFactory + { + IKubeApiClient Get(KubeRegistryConfiguration config); + } +} diff --git a/src/Ocelot.Provider.Kubernetes/KubeApiClientFactory.cs b/src/Ocelot.Provider.Kubernetes/KubeApiClientFactory.cs new file mode 100644 index 00000000..fbb832ba --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/KubeApiClientFactory.cs @@ -0,0 +1,22 @@ +using KubeClient; + +namespace Ocelot.Provider.Kubernetes +{ + public class KubeApiClientFactory : IKubeApiClientFactory + { + public IKubeApiClient Get(KubeRegistryConfiguration config) + { + var option = new KubeClientOptions + { + ApiEndPoint = config.ApiEndPoint + }; + if(!string.IsNullOrEmpty(config?.AccessToken)) + { + option.AccessToken = config.AccessToken; + option.AuthStrategy = config.AuthStrategy; + option.AllowInsecure = config.AllowInsecure; + } + return KubeApiClient.Create(option); + } + } +} diff --git a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs new file mode 100644 index 00000000..72c627de --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs @@ -0,0 +1,59 @@ +using KubeClient; +using KubeClient.Models; +using Ocelot.Logging; +using Ocelot.ServiceDiscovery.Providers; +using Ocelot.Values; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Ocelot.Provider.Kubernetes +{ + public class KubeProvider : IServiceDiscoveryProvider + { + private KubeRegistryConfiguration kubeRegistryConfiguration; + private IOcelotLoggerFactory factory; + private IKubeApiClient kubeApi; + private IKubeApiClientFactory kubeClientFactory; + + public KubeProvider(KubeRegistryConfiguration kubeRegistryConfiguration, IOcelotLoggerFactory factory, IKubeApiClientFactory kubeClientFactory) + { + this.kubeRegistryConfiguration = kubeRegistryConfiguration; + this.factory = factory; + this.kubeApi = kubeClientFactory.Get(kubeRegistryConfiguration); + } + + public async Task> Get() + { + var service = await kubeApi.ServicesV1().Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); + var services = new List(); + if (IsValid(service)) + { + services.Add(BuildService(service)); + } + return services; + } + + private bool IsValid(ServiceV1 service) + { + if (string.IsNullOrEmpty(service.Spec.ClusterIP) || service.Spec.Ports.Count <= 0) + { + return false; + } + + return true; + } + + private Service BuildService(ServiceV1 serviceEntry) + { + var servicePort = serviceEntry.Spec.Ports.FirstOrDefault(); + return new Service( + serviceEntry.Metadata.Name, + new ServiceHostAndPort(serviceEntry.Spec.ClusterIP, servicePort.Port), + serviceEntry.Metadata.Uid, + string.Empty, + Enumerable.Empty()); + } + } +} diff --git a/src/Ocelot.Provider.Kubernetes/KubeRegistryConfiguration.cs b/src/Ocelot.Provider.Kubernetes/KubeRegistryConfiguration.cs new file mode 100644 index 00000000..929c6e32 --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/KubeRegistryConfiguration.cs @@ -0,0 +1,22 @@ +using KubeClient; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ocelot.Provider.Kubernetes +{ + public class KubeRegistryConfiguration + { + public Uri ApiEndPoint { get; set; } + + public string KubeNamespace { get; set; } + + public string KeyOfServiceInK8s { get; set; } + + public KubeAuthStrategy AuthStrategy { get; set; } + + public string AccessToken { get; set; } + + public bool AllowInsecure { get; set; } + } +} diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs new file mode 100644 index 00000000..528a9115 --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -0,0 +1,31 @@ +using KubeClient; +using Microsoft.Extensions.DependencyInjection; +using Ocelot.Logging; +using Ocelot.ServiceDiscovery; +using System; + +namespace Ocelot.Provider.Kubernetes +{ + public static class KubernetesProviderFactory + { + public static ServiceDiscoveryFinderDelegate Get = (provider, config, name) => + { + var factory = provider.GetService(); + + var kubeClientFactory = provider.GetService(); + + var k8sRegistryConfiguration = new KubeRegistryConfiguration() { + ApiEndPoint = new Uri($"http://{config.Host}:{config.Port}"), + KeyOfServiceInK8s = name, + KubeNamespace = config.Namesapce, + AuthStrategy = KubeAuthStrategy.BearerToken, + AccessToken = config.Token, + AllowInsecure = true // Don't validate server certificate + }; + + var k8sServiceDiscoveryProvider = new KubeProvider(k8sRegistryConfiguration, factory, kubeClientFactory); + + return k8sServiceDiscoveryProvider; + }; + } +} diff --git a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj new file mode 100644 index 00000000..b97b8c82 --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + + + + + + + + + + + diff --git a/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs b/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs new file mode 100644 index 00000000..d206a6c7 --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs @@ -0,0 +1,20 @@ +using KubeClient; +using Microsoft.Extensions.DependencyInjection; +using Ocelot.DependencyInjection; +using Ocelot.ServiceDiscovery; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Ocelot.Provider.Kubernetes +{ + public static class OcelotBuilderExtensions + { + public static IOcelotBuilder AddKubernetes(this IOcelotBuilder builder) + { + builder.Services.AddSingleton(KubernetesProviderFactory.Get); + builder.Services.AddSingleton(); + return builder; + } + } +} diff --git a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs index 1ea18067..e9cc947f 100644 --- a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs @@ -8,6 +8,7 @@ namespace Ocelot.Configuration.Builder private string _token; private string _configurationKey; private int _pollingInterval; + private string _namespace; public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost) { @@ -45,9 +46,15 @@ namespace Ocelot.Configuration.Builder return this; } + public ServiceProviderConfigurationBuilder WithNamesapce(string @namesapce) + { + _namespace = @namesapce; + return this; + } + public ServiceProviderConfiguration Build() { - return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token, _configurationKey, _pollingInterval); + return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token, _configurationKey, _pollingInterval, _namespace); } } } diff --git a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs index a236fb22..88137a8b 100644 --- a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs @@ -13,6 +13,7 @@ namespace Ocelot.Configuration.Creator ? globalConfiguration?.ServiceDiscoveryProvider?.Type : "consul"; var pollingInterval = globalConfiguration?.ServiceDiscoveryProvider?.PollingInterval ?? 0; + var k8snamesapce = globalConfiguration?.ServiceDiscoveryProvider?.Namespace ?? string.Empty; return new ServiceProviderConfigurationBuilder() .WithHost(host) @@ -21,6 +22,7 @@ namespace Ocelot.Configuration.Creator .WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token) .WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey) .WithPollingInterval(pollingInterval) + .WithNamesapce(k8snamesapce) .Build(); } } diff --git a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs index e6edeee7..153145bd 100644 --- a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs +++ b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs @@ -8,5 +8,6 @@ namespace Ocelot.Configuration.File public string Token { get; set; } public string ConfigurationKey { get; set; } public int PollingInterval { get; set; } + public string Namespace { get; set; } } } diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguration.cs b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs index 72c3abfb..05ee07d4 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguration.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs @@ -2,7 +2,7 @@ { public class ServiceProviderConfiguration { - public ServiceProviderConfiguration(string type, string host, int port, string token, string configurationKey, int pollingInterval) + public ServiceProviderConfiguration(string type, string host, int port, string token, string configurationKey, int pollingInterval, string @namespace = "") { ConfigurationKey = configurationKey; Host = host; @@ -10,13 +10,21 @@ Token = token; Type = type; PollingInterval = pollingInterval; + Namesapce = @namespace; } public string Host { get; } + public int Port { get; } + public string Type { get; } + public string Token { get; } + public string ConfigurationKey { get; } + public int PollingInterval { get; } + + public string Namesapce { get; } } } diff --git a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs index 4bdf014b..d93e6911 100644 --- a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs +++ b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs @@ -434,7 +434,8 @@ Host = "localhost", Port = consulPort, Type = "PollConsul", - PollingInterval = 0 + PollingInterval = 0, + Namespace = string.Empty } } }; diff --git a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs index f1ec3a07..fcf0c52a 100644 --- a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs @@ -30,7 +30,8 @@ namespace Ocelot.UnitTests.Configuration Port = 1234, Type = "ServiceFabric", Token = "testtoken", - ConfigurationKey = "woo" + ConfigurationKey = "woo", + Namespace ="default" } }; @@ -40,13 +41,14 @@ namespace Ocelot.UnitTests.Configuration .WithType("ServiceFabric") .WithToken("testtoken") .WithConfigurationKey("woo") + .WithNamesapce("default") .Build(); this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig)) .When(x => x.WhenICreate()) .Then(x => x.ThenTheConfigIs(expected)) .BDDfy(); - } + } private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration fileGlobalConfig) { @@ -64,6 +66,7 @@ namespace Ocelot.UnitTests.Configuration _result.Port.ShouldBe(expected.Port); _result.Token.ShouldBe(expected.Token); _result.Type.ShouldBe(expected.Type); + _result.Namesapce.ShouldBe(expected.Namesapce); _result.ConfigurationKey.ShouldBe(expected.ConfigurationKey); } } From 23248b080eff80f2e3d65d8543e90c51aae22efe Mon Sep 17 00:00:00 2001 From: geffzhang Date: Sat, 19 Jan 2019 17:16:24 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E7=BC=96=E5=86=99k8s=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E4=BE=8B=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samples/OelotKube/.dockerignore | 9 ++++ .../OelotKube/ApiGateway/ApiGateway.csproj | 21 ++++++++ samples/OelotKube/ApiGateway/Dockerfile | 19 +++++++ samples/OelotKube/ApiGateway/Program.cs | 33 +++++++++++++ .../ApiGateway/Properties/launchSettings.json | 32 ++++++++++++ samples/OelotKube/ApiGateway/Startup.cs | 38 ++++++++++++++ .../ApiGateway/appsettings.Development.json | 9 ++++ samples/OelotKube/ApiGateway/appsettings.json | 8 +++ samples/OelotKube/ApiGateway/ocelot.json | 27 ++++++++++ .../Controllers/ValuesController.cs | 45 +++++++++++++++++ .../OelotKube/DownstreamService/Dockerfile | 19 +++++++ .../DownstreamService.csproj | 15 ++++++ .../OelotKube/DownstreamService/Program.cs | 24 +++++++++ .../Properties/launchSettings.json | 35 +++++++++++++ .../OelotKube/DownstreamService/Startup.cs | 41 ++++++++++++++++ .../appsettings.Development.json | 9 ++++ .../DownstreamService/appsettings.json | 8 +++ samples/OelotKube/OelotKube.sln | 49 +++++++++++++++++++ .../KubernetesProviderFactory.cs | 16 ++++-- 19 files changed, 453 insertions(+), 4 deletions(-) create mode 100644 samples/OelotKube/.dockerignore create mode 100644 samples/OelotKube/ApiGateway/ApiGateway.csproj create mode 100644 samples/OelotKube/ApiGateway/Dockerfile create mode 100644 samples/OelotKube/ApiGateway/Program.cs create mode 100644 samples/OelotKube/ApiGateway/Properties/launchSettings.json create mode 100644 samples/OelotKube/ApiGateway/Startup.cs create mode 100644 samples/OelotKube/ApiGateway/appsettings.Development.json create mode 100644 samples/OelotKube/ApiGateway/appsettings.json create mode 100644 samples/OelotKube/ApiGateway/ocelot.json create mode 100644 samples/OelotKube/DownstreamService/Controllers/ValuesController.cs create mode 100644 samples/OelotKube/DownstreamService/Dockerfile create mode 100644 samples/OelotKube/DownstreamService/DownstreamService.csproj create mode 100644 samples/OelotKube/DownstreamService/Program.cs create mode 100644 samples/OelotKube/DownstreamService/Properties/launchSettings.json create mode 100644 samples/OelotKube/DownstreamService/Startup.cs create mode 100644 samples/OelotKube/DownstreamService/appsettings.Development.json create mode 100644 samples/OelotKube/DownstreamService/appsettings.json create mode 100644 samples/OelotKube/OelotKube.sln diff --git a/samples/OelotKube/.dockerignore b/samples/OelotKube/.dockerignore new file mode 100644 index 00000000..df2e0fe5 --- /dev/null +++ b/samples/OelotKube/.dockerignore @@ -0,0 +1,9 @@ +.dockerignore +.env +.git +.gitignore +.vs +.vscode +*/bin +*/obj +**/.toolstarget \ No newline at end of file diff --git a/samples/OelotKube/ApiGateway/ApiGateway.csproj b/samples/OelotKube/ApiGateway/ApiGateway.csproj new file mode 100644 index 00000000..ab5b5e80 --- /dev/null +++ b/samples/OelotKube/ApiGateway/ApiGateway.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.1 + InProcess + Linux + + + + + + + + + + + + + + + diff --git a/samples/OelotKube/ApiGateway/Dockerfile b/samples/OelotKube/ApiGateway/Dockerfile new file mode 100644 index 00000000..5abcd05a --- /dev/null +++ b/samples/OelotKube/ApiGateway/Dockerfile @@ -0,0 +1,19 @@ +FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/dotnet:2.2-sdk AS build +WORKDIR /src +COPY ["ApiGateway/ApiGateway.csproj", "ApiGateway/"] +RUN dotnet restore "ApiGateway/ApiGateway.csproj" +COPY . . +WORKDIR "/src/ApiGateway" +RUN dotnet build "ApiGateway.csproj" -c Release -o /app + +FROM build AS publish +RUN dotnet publish "ApiGateway.csproj" -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "ApiGateway.dll"] \ No newline at end of file diff --git a/samples/OelotKube/ApiGateway/Program.cs b/samples/OelotKube/ApiGateway/Program.cs new file mode 100644 index 00000000..0b55041c --- /dev/null +++ b/samples/OelotKube/ApiGateway/Program.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; +using Ocelot.Provider.Kubernetes; + +namespace ApiGateway +{ + public class Program + { + public static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + public static IWebHost BuildWebHost(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseUrls("http://localhost:5000") + .ConfigureAppConfiguration((hostingContext, config) => + { + config + .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", true, true) + .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) + .AddJsonFile("ocelot.json", false, false) + .AddEnvironmentVariables(); + }) + .UseStartup() + .Build(); + } +} + diff --git a/samples/OelotKube/ApiGateway/Properties/launchSettings.json b/samples/OelotKube/ApiGateway/Properties/launchSettings.json new file mode 100644 index 00000000..5315ab2c --- /dev/null +++ b/samples/OelotKube/ApiGateway/Properties/launchSettings.json @@ -0,0 +1,32 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52363", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "ApiGateway": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000" + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://localhost:{ServicePort}" + } + } +} \ No newline at end of file diff --git a/samples/OelotKube/ApiGateway/Startup.cs b/samples/OelotKube/ApiGateway/Startup.cs new file mode 100644 index 00000000..6b7b68f2 --- /dev/null +++ b/samples/OelotKube/ApiGateway/Startup.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; +using Ocelot.Provider.Kubernetes; +using Ocelot.Provider.Polly; + +namespace ApiGateway +{ + public class Startup + { + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public void ConfigureServices(IServiceCollection services) + { + services.AddOcelot() + .AddPolly() + .AddKubernetes(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseOcelot().Wait(); + } + } +} diff --git a/samples/OelotKube/ApiGateway/appsettings.Development.json b/samples/OelotKube/ApiGateway/appsettings.Development.json new file mode 100644 index 00000000..e203e940 --- /dev/null +++ b/samples/OelotKube/ApiGateway/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/samples/OelotKube/ApiGateway/appsettings.json b/samples/OelotKube/ApiGateway/appsettings.json new file mode 100644 index 00000000..def9159a --- /dev/null +++ b/samples/OelotKube/ApiGateway/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/OelotKube/ApiGateway/ocelot.json b/samples/OelotKube/ApiGateway/ocelot.json new file mode 100644 index 00000000..7099261c --- /dev/null +++ b/samples/OelotKube/ApiGateway/ocelot.json @@ -0,0 +1,27 @@ +{ + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/Category", + "DownstreamScheme": "http", + "UpstreamPathTemplate": "/Category", + "ServiceName": "DownstreamService", + "UpstreamHttpMethod": [ "Get" ], + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 10000, + "TimeoutValue": 5000 + }, + "FileCacheOptions": { "TtlSeconds": 15 } + } + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration", + "ServiceDiscoveryProvider": { + "Host": "localhost", + "Port": 8001, + "Namesapce": "dev", + "Type": "k8s" + } + } +} diff --git a/samples/OelotKube/DownstreamService/Controllers/ValuesController.cs b/samples/OelotKube/DownstreamService/Controllers/ValuesController.cs new file mode 100644 index 00000000..425cf18d --- /dev/null +++ b/samples/OelotKube/DownstreamService/Controllers/ValuesController.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace DownstreamService.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ValuesController : ControllerBase + { + // GET api/values + [HttpGet] + public ActionResult> Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public ActionResult Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody] string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody] string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/samples/OelotKube/DownstreamService/Dockerfile b/samples/OelotKube/DownstreamService/Dockerfile new file mode 100644 index 00000000..baa13993 --- /dev/null +++ b/samples/OelotKube/DownstreamService/Dockerfile @@ -0,0 +1,19 @@ +FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/dotnet:2.2-sdk AS build +WORKDIR /src +COPY ["DownstreamService/DownstreamService.csproj", "DownstreamService/"] +RUN dotnet restore "DownstreamService/DownstreamService.csproj" +COPY . . +WORKDIR "/src/DownstreamService" +RUN dotnet build "DownstreamService.csproj" -c Release -o /app + +FROM build AS publish +RUN dotnet publish "DownstreamService.csproj" -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "DownstreamService.dll"] \ No newline at end of file diff --git a/samples/OelotKube/DownstreamService/DownstreamService.csproj b/samples/OelotKube/DownstreamService/DownstreamService.csproj new file mode 100644 index 00000000..c32dd048 --- /dev/null +++ b/samples/OelotKube/DownstreamService/DownstreamService.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp2.1 + InProcess + Linux + + + + + + + + + diff --git a/samples/OelotKube/DownstreamService/Program.cs b/samples/OelotKube/DownstreamService/Program.cs new file mode 100644 index 00000000..03e1b8ae --- /dev/null +++ b/samples/OelotKube/DownstreamService/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace DownstreamService +{ + public class Program + { + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/samples/OelotKube/DownstreamService/Properties/launchSettings.json b/samples/OelotKube/DownstreamService/Properties/launchSettings.json new file mode 100644 index 00000000..30d6118c --- /dev/null +++ b/samples/OelotKube/DownstreamService/Properties/launchSettings.json @@ -0,0 +1,35 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:56411", + "sslPort": 0 + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "DownstreamService": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000" + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/api/values" + } + } +} \ No newline at end of file diff --git a/samples/OelotKube/DownstreamService/Startup.cs b/samples/OelotKube/DownstreamService/Startup.cs new file mode 100644 index 00000000..9a927a37 --- /dev/null +++ b/samples/OelotKube/DownstreamService/Startup.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace DownstreamService +{ + public class Startup + { + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseMvc(); + } + } +} diff --git a/samples/OelotKube/DownstreamService/appsettings.Development.json b/samples/OelotKube/DownstreamService/appsettings.Development.json new file mode 100644 index 00000000..e203e940 --- /dev/null +++ b/samples/OelotKube/DownstreamService/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/samples/OelotKube/DownstreamService/appsettings.json b/samples/OelotKube/DownstreamService/appsettings.json new file mode 100644 index 00000000..def9159a --- /dev/null +++ b/samples/OelotKube/DownstreamService/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/samples/OelotKube/OelotKube.sln b/samples/OelotKube/OelotKube.sln new file mode 100644 index 00000000..ed31dc9d --- /dev/null +++ b/samples/OelotKube/OelotKube.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2048 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiGateway", "ApiGateway\ApiGateway.csproj", "{E9AFBFD7-EF20-48E5-BB30-5C63C59D7C1C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot", "..\..\src\Ocelot\Ocelot.csproj", "{E8551073-622E-45FA-AD09-038EB8AAFFBC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Kubernetes", "..\..\src\Ocelot.Provider.Kubernetes\Ocelot.Provider.Kubernetes.csproj", "{EF973868-98A6-4864-BF66-65B5A8C123FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Polly", "..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj", "{323055CB-BF62-4A31-A619-A4444B633CDB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownstreamService", "DownstreamService\DownstreamService.csproj", "{86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E9AFBFD7-EF20-48E5-BB30-5C63C59D7C1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9AFBFD7-EF20-48E5-BB30-5C63C59D7C1C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9AFBFD7-EF20-48E5-BB30-5C63C59D7C1C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9AFBFD7-EF20-48E5-BB30-5C63C59D7C1C}.Release|Any CPU.Build.0 = Release|Any CPU + {E8551073-622E-45FA-AD09-038EB8AAFFBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8551073-622E-45FA-AD09-038EB8AAFFBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8551073-622E-45FA-AD09-038EB8AAFFBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8551073-622E-45FA-AD09-038EB8AAFFBC}.Release|Any CPU.Build.0 = Release|Any CPU + {EF973868-98A6-4864-BF66-65B5A8C123FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF973868-98A6-4864-BF66-65B5A8C123FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF973868-98A6-4864-BF66-65B5A8C123FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF973868-98A6-4864-BF66-65B5A8C123FE}.Release|Any CPU.Build.0 = Release|Any CPU + {323055CB-BF62-4A31-A619-A4444B633CDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {323055CB-BF62-4A31-A619-A4444B633CDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {323055CB-BF62-4A31-A619-A4444B633CDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {323055CB-BF62-4A31-A619-A4444B633CDB}.Release|Any CPU.Build.0 = Release|Any CPU + {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D29790E8-4BA9-4E60-8D7D-327E21320CC9} + EndGlobalSection +EndGlobal diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 528a9115..074e926d 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -11,10 +11,18 @@ namespace Ocelot.Provider.Kubernetes public static ServiceDiscoveryFinderDelegate Get = (provider, config, name) => { var factory = provider.GetService(); - - var kubeClientFactory = provider.GetService(); + if (config.Type?.ToLower() == "k8s") + { + return GetkubeProvider(provider, config, name, factory); + } + return null; + }; - var k8sRegistryConfiguration = new KubeRegistryConfiguration() { + private static ServiceDiscovery.Providers.IServiceDiscoveryProvider GetkubeProvider(IServiceProvider provider, Configuration.ServiceProviderConfiguration config, string name, IOcelotLoggerFactory factory) + { + var kubeClientFactory = provider.GetService(); + var k8sRegistryConfiguration = new KubeRegistryConfiguration() + { ApiEndPoint = new Uri($"http://{config.Host}:{config.Port}"), KeyOfServiceInK8s = name, KubeNamespace = config.Namesapce, @@ -26,6 +34,6 @@ namespace Ocelot.Provider.Kubernetes var k8sServiceDiscoveryProvider = new KubeProvider(k8sRegistryConfiguration, factory, kubeClientFactory); return k8sServiceDiscoveryProvider; - }; + } } } From c212604b85e27b551539ca95f87d10575c1749e2 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Sun, 20 Jan 2019 13:17:57 +0800 Subject: [PATCH 03/19] =?UTF-8?q?feat=EF=BC=9Afix=20kube=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samples/OelotKube/ApiGateway/Dockerfile | 9 +++++--- samples/OelotKube/ApiGateway/ocelot.json | 4 ++-- samples/OelotKube/Dockerfile | 22 +++++++++++++++++++ .../OelotKube/DownstreamService/Dockerfile | 6 ++--- .../DownstreamService/Dockerfile.develop | 15 +++++++++++++ samples/OelotKube/OelotKube.sln | 2 +- .../KubeProvider.cs | 4 ++-- .../KubernetesProviderFactory.cs | 4 ++-- 8 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 samples/OelotKube/Dockerfile create mode 100644 samples/OelotKube/DownstreamService/Dockerfile.develop diff --git a/samples/OelotKube/ApiGateway/Dockerfile b/samples/OelotKube/ApiGateway/Dockerfile index 5abcd05a..1ec13d2a 100644 --- a/samples/OelotKube/ApiGateway/Dockerfile +++ b/samples/OelotKube/ApiGateway/Dockerfile @@ -1,10 +1,13 @@ -FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base +FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 -FROM microsoft/dotnet:2.2-sdk AS build +FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["ApiGateway/ApiGateway.csproj", "ApiGateway/"] +COPY ["../../src/Ocelot.Provider.Polly/Ocelot.Provider.Polly.csproj", "../../src/Ocelot.Provider.Polly/"] +COPY ["../../src/Ocelot/Ocelot.csproj", "../../src/Ocelot/"] +COPY ["../../src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj", "../../src/Ocelot.Provider.Kubernetes/"] RUN dotnet restore "ApiGateway/ApiGateway.csproj" COPY . . WORKDIR "/src/ApiGateway" @@ -16,4 +19,4 @@ RUN dotnet publish "ApiGateway.csproj" -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . -ENTRYPOINT ["dotnet", "ApiGateway.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "ApiGateway.dll"] diff --git a/samples/OelotKube/ApiGateway/ocelot.json b/samples/OelotKube/ApiGateway/ocelot.json index 7099261c..4830a359 100644 --- a/samples/OelotKube/ApiGateway/ocelot.json +++ b/samples/OelotKube/ApiGateway/ocelot.json @@ -1,7 +1,7 @@ { "ReRoutes": [ { - "DownstreamPathTemplate": "/api/Category", + "DownstreamPathTemplate": "/api/values", "DownstreamScheme": "http", "UpstreamPathTemplate": "/Category", "ServiceName": "DownstreamService", @@ -21,7 +21,7 @@ "Host": "localhost", "Port": 8001, "Namesapce": "dev", - "Type": "k8s" + "Type": "kube" } } } diff --git a/samples/OelotKube/Dockerfile b/samples/OelotKube/Dockerfile new file mode 100644 index 00000000..1ec13d2a --- /dev/null +++ b/samples/OelotKube/Dockerfile @@ -0,0 +1,22 @@ +FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base +WORKDIR /app +EXPOSE 80 + +FROM microsoft/dotnet:2.1-sdk AS build +WORKDIR /src +COPY ["ApiGateway/ApiGateway.csproj", "ApiGateway/"] +COPY ["../../src/Ocelot.Provider.Polly/Ocelot.Provider.Polly.csproj", "../../src/Ocelot.Provider.Polly/"] +COPY ["../../src/Ocelot/Ocelot.csproj", "../../src/Ocelot/"] +COPY ["../../src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj", "../../src/Ocelot.Provider.Kubernetes/"] +RUN dotnet restore "ApiGateway/ApiGateway.csproj" +COPY . . +WORKDIR "/src/ApiGateway" +RUN dotnet build "ApiGateway.csproj" -c Release -o /app + +FROM build AS publish +RUN dotnet publish "ApiGateway.csproj" -c Release -o /app + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +ENTRYPOINT ["dotnet", "ApiGateway.dll"] diff --git a/samples/OelotKube/DownstreamService/Dockerfile b/samples/OelotKube/DownstreamService/Dockerfile index baa13993..a9695515 100644 --- a/samples/OelotKube/DownstreamService/Dockerfile +++ b/samples/OelotKube/DownstreamService/Dockerfile @@ -1,8 +1,8 @@ -FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base +FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 -FROM microsoft/dotnet:2.2-sdk AS build +FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["DownstreamService/DownstreamService.csproj", "DownstreamService/"] RUN dotnet restore "DownstreamService/DownstreamService.csproj" @@ -16,4 +16,4 @@ RUN dotnet publish "DownstreamService.csproj" -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . -ENTRYPOINT ["dotnet", "DownstreamService.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "DownstreamService.dll"] diff --git a/samples/OelotKube/DownstreamService/Dockerfile.develop b/samples/OelotKube/DownstreamService/Dockerfile.develop new file mode 100644 index 00000000..6f49a290 --- /dev/null +++ b/samples/OelotKube/DownstreamService/Dockerfile.develop @@ -0,0 +1,15 @@ +FROM microsoft/dotnet:2.1-sdk +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src +COPY ["DownstreamService/DownstreamService.csproj", "DownstreamService/"] + +RUN dotnet restore "DownstreamService/DownstreamService.csproj" +COPY . . +WORKDIR "/src/DownstreamService" +RUN dotnet build --no-restore "DownstreamService.csproj" -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] \ No newline at end of file diff --git a/samples/OelotKube/OelotKube.sln b/samples/OelotKube/OelotKube.sln index ed31dc9d..2bb63eff 100644 --- a/samples/OelotKube/OelotKube.sln +++ b/samples/OelotKube/OelotKube.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Kubernetes" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Polly", "..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj", "{323055CB-BF62-4A31-A619-A4444B633CDB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownstreamService", "DownstreamService\DownstreamService.csproj", "{86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DownstreamService", "DownstreamService\DownstreamService.csproj", "{86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs index 72c627de..eb3a23b2 100644 --- a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs +++ b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs @@ -10,14 +10,14 @@ using System.Threading.Tasks; namespace Ocelot.Provider.Kubernetes { - public class KubeProvider : IServiceDiscoveryProvider + public class Kube : IServiceDiscoveryProvider { private KubeRegistryConfiguration kubeRegistryConfiguration; private IOcelotLoggerFactory factory; private IKubeApiClient kubeApi; private IKubeApiClientFactory kubeClientFactory; - public KubeProvider(KubeRegistryConfiguration kubeRegistryConfiguration, IOcelotLoggerFactory factory, IKubeApiClientFactory kubeClientFactory) + public Kube(KubeRegistryConfiguration kubeRegistryConfiguration, IOcelotLoggerFactory factory, IKubeApiClientFactory kubeClientFactory) { this.kubeRegistryConfiguration = kubeRegistryConfiguration; this.factory = factory; diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 074e926d..56416ee6 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -11,7 +11,7 @@ namespace Ocelot.Provider.Kubernetes public static ServiceDiscoveryFinderDelegate Get = (provider, config, name) => { var factory = provider.GetService(); - if (config.Type?.ToLower() == "k8s") + if (config.Type?.ToLower() == "kube") { return GetkubeProvider(provider, config, name, factory); } @@ -31,7 +31,7 @@ namespace Ocelot.Provider.Kubernetes AllowInsecure = true // Don't validate server certificate }; - var k8sServiceDiscoveryProvider = new KubeProvider(k8sRegistryConfiguration, factory, kubeClientFactory); + var k8sServiceDiscoveryProvider = new Kube(k8sRegistryConfiguration, factory, kubeClientFactory); return k8sServiceDiscoveryProvider; } From b9ff7802bdc1b3b8aa026a01eb1a44e696217044 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Sun, 20 Jan 2019 13:19:39 +0800 Subject: [PATCH 04/19] =?UTF-8?q?feat=EF=BC=9A=20remove=20port?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samples/OelotKube/ApiGateway/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/samples/OelotKube/ApiGateway/Program.cs b/samples/OelotKube/ApiGateway/Program.cs index 0b55041c..978c8ccc 100644 --- a/samples/OelotKube/ApiGateway/Program.cs +++ b/samples/OelotKube/ApiGateway/Program.cs @@ -16,7 +16,6 @@ namespace ApiGateway public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) - .UseUrls("http://localhost:5000") .ConfigureAppConfiguration((hostingContext, config) => { config From 7f73bd3a64f195c3edf27e982f69829f276b7a19 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 29 Jan 2019 09:15:30 +0800 Subject: [PATCH 05/19] =?UTF-8?q?feat=20=EF=BC=9A=20complete=20the=20k8s?= =?UTF-8?q?=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs | 2 +- .../Ocelot.Provider.Kubernetes.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 56416ee6..34561e0a 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -23,7 +23,7 @@ namespace Ocelot.Provider.Kubernetes var kubeClientFactory = provider.GetService(); var k8sRegistryConfiguration = new KubeRegistryConfiguration() { - ApiEndPoint = new Uri($"http://{config.Host}:{config.Port}"), + ApiEndPoint = new Uri($"https://{config.Host}:{config.Port}"), KeyOfServiceInK8s = name, KubeNamespace = config.Namesapce, AuthStrategy = KubeAuthStrategy.BearerToken, diff --git a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj index b97b8c82..7a82d52f 100644 --- a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj +++ b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj @@ -5,7 +5,7 @@ - + From b1cd23459ee316ab126ad66a4fc4c4186cecdfd2 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 29 Jan 2019 11:31:26 +0800 Subject: [PATCH 06/19] 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 @@ - + From 1f5c71b45c3b0dcdd42edaa8ec895d39e2dc0c54 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 29 Jan 2019 12:20:38 +0800 Subject: [PATCH 07/19] feat : add kube provider unittest --- .../Kubernetes/KubeProviderFactoryTests.cs | 35 ++++++++++ .../KubeServiceDiscoveryProviderTests.cs | 1 - .../OcelotBuilderExtensionsTests.cs | 70 +++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs create mode 100644 test/Ocelot.UnitTests/Kubernetes/OcelotBuilderExtensionsTests.cs diff --git a/test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs b/test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs new file mode 100644 index 00000000..0627e7ba --- /dev/null +++ b/test/Ocelot.UnitTests/Kubernetes/KubeProviderFactoryTests.cs @@ -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(); + var logger = new Mock(); + loggerFactory.Setup(x => x.CreateLogger()).Returns(logger.Object); + var kubeFactory = new Mock(); + 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(); + } + } +} diff --git a/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs index bf4bab80..d0db1507 100644 --- a/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs +++ b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs @@ -12,7 +12,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using TestStack.BDDfy; using Xunit; diff --git a/test/Ocelot.UnitTests/Kubernetes/OcelotBuilderExtensionsTests.cs b/test/Ocelot.UnitTests/Kubernetes/OcelotBuilderExtensionsTests.cs new file mode 100644 index 00000000..103f94aa --- /dev/null +++ b/test/Ocelot.UnitTests/Kubernetes/OcelotBuilderExtensionsTests.cs @@ -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()); + _services = new ServiceCollection(); + _services.AddSingleton(); + _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(); + } + } +} From 635c293a6d0368115cc2aa609f12b24f11e63208 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 29 Jan 2019 12:41:46 +0800 Subject: [PATCH 08/19] feat :add kubetnetes docs how to use ocelot with kubetnetes docs --- docs/features/kubernetes.rst | 56 ++++++++++++++++++++++++++++++++++++ docs/index.rst | 3 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 docs/features/kubernetes.rst diff --git a/docs/features/kubernetes.rst b/docs/features/kubernetes.rst new file mode 100644 index 00000000..30b57a9b --- /dev/null +++ b/docs/features/kubernetes.rst @@ -0,0 +1,56 @@ +Kubernetes +============== + +This feature was requested as part of `Issue 345 `_ . to add support for kubernetes's service discovery provider. + +The first thing you need to do is install the NuGet package that provides kubernetes support in Ocelot. + +``Install-Package Ocelot.Provider.Kubernetes`` + +Then add the following to your ConfigureServices method. + +.. code-block:: csharp + + s.AddOcelot() + .AddKubernetes(); + +If you have services deployed in kubernetes you will normally use the naming service to access them. + +The following example shows how to set up a ReRoute that will work in kubernetes. The most important thing is the ServiceName which is made up of the +kubernetes service name. We also need to set up the ServiceDiscoveryProvider in +GlobalConfiguration. The example here shows a typical configuration. It assumes kubernetes api server is running on 192.168.0.13 and that the api service is on port 443. + +The example below is taken from the samples folder so please check it if this doesnt make sense! + +.. code-block:: json + + { + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/values", + "DownstreamScheme": "http", + "UpstreamPathTemplate": "/values", + "ServiceName": "downstreamservice", + "UpstreamHttpMethod": [ "Get" ], + "QoSOptions": { + "ExceptionsAllowedBeforeBreaking": 3, + "DurationOfBreak": 10000, + "TimeoutValue": 5000 + }, + "FileCacheOptions": { "TtlSeconds": 15 } + } + ], + "GlobalConfiguration": { + "RequestIdKey": "OcRequestId", + "AdministrationPath": "/administration", + "ServiceDiscoveryProvider": { + "Host": "192.168.0.13", + "Port": 443, + "Token": "txpc696iUhbVoudg164r93CxDTrKRVWG", + "Namespace": "dev", + "Type": "kube" + } + } +} + +There is no way for Ocelot to work these out for you. diff --git a/docs/index.rst b/docs/index.rst index 7989fcdd..4aba33fd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,7 +23,8 @@ Thanks for taking a look at the Ocelot documentation. Please use the left hand n features/requestaggregation features/graphql features/servicediscovery - features/servicefabric + features/servicefabric + features/kubernetes features/authentication features/authorisation features/websockets From bd7e18ca42642921b5ae19f9a092e5e736e51826 Mon Sep 17 00:00:00 2001 From: geffzhang <136590076@qq.com> Date: Wed, 30 Jan 2019 07:36:19 +0800 Subject: [PATCH 09/19] keep the configuration as simple as possible, no qos, no cache --- samples/OelotKube/ApiGateway/ApiGateway.csproj | 1 - samples/OelotKube/ApiGateway/Startup.cs | 2 -- samples/OelotKube/ApiGateway/ocelot.json | 8 +------- samples/OelotKube/OelotKube.sln | 6 ------ 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/samples/OelotKube/ApiGateway/ApiGateway.csproj b/samples/OelotKube/ApiGateway/ApiGateway.csproj index ab5b5e80..aef8c150 100644 --- a/samples/OelotKube/ApiGateway/ApiGateway.csproj +++ b/samples/OelotKube/ApiGateway/ApiGateway.csproj @@ -14,7 +14,6 @@ - diff --git a/samples/OelotKube/ApiGateway/Startup.cs b/samples/OelotKube/ApiGateway/Startup.cs index 6b7b68f2..4743e836 100644 --- a/samples/OelotKube/ApiGateway/Startup.cs +++ b/samples/OelotKube/ApiGateway/Startup.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; using Ocelot.Middleware; using Ocelot.Provider.Kubernetes; -using Ocelot.Provider.Polly; namespace ApiGateway { @@ -20,7 +19,6 @@ namespace ApiGateway public void ConfigureServices(IServiceCollection services) { services.AddOcelot() - .AddPolly() .AddKubernetes(); } diff --git a/samples/OelotKube/ApiGateway/ocelot.json b/samples/OelotKube/ApiGateway/ocelot.json index eabb960b..efe3f36f 100644 --- a/samples/OelotKube/ApiGateway/ocelot.json +++ b/samples/OelotKube/ApiGateway/ocelot.json @@ -5,13 +5,7 @@ "DownstreamScheme": "http", "UpstreamPathTemplate": "/values", "ServiceName": "downstreamservice", - "UpstreamHttpMethod": [ "Get" ], - "QoSOptions": { - "ExceptionsAllowedBeforeBreaking": 3, - "DurationOfBreak": 10000, - "TimeoutValue": 5000 - }, - "FileCacheOptions": { "TtlSeconds": 15 } + "UpstreamHttpMethod": [ "Get" ] } ], "GlobalConfiguration": { diff --git a/samples/OelotKube/OelotKube.sln b/samples/OelotKube/OelotKube.sln index 2bb63eff..aa57e0dd 100644 --- a/samples/OelotKube/OelotKube.sln +++ b/samples/OelotKube/OelotKube.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot", "..\..\src\Ocelot\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Kubernetes", "..\..\src\Ocelot.Provider.Kubernetes\Ocelot.Provider.Kubernetes.csproj", "{EF973868-98A6-4864-BF66-65B5A8C123FE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Polly", "..\..\src\Ocelot.Provider.Polly\Ocelot.Provider.Polly.csproj", "{323055CB-BF62-4A31-A619-A4444B633CDB}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DownstreamService", "DownstreamService\DownstreamService.csproj", "{86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}" EndProject Global @@ -31,10 +29,6 @@ Global {EF973868-98A6-4864-BF66-65B5A8C123FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {EF973868-98A6-4864-BF66-65B5A8C123FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {EF973868-98A6-4864-BF66-65B5A8C123FE}.Release|Any CPU.Build.0 = Release|Any CPU - {323055CB-BF62-4A31-A619-A4444B633CDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {323055CB-BF62-4A31-A619-A4444B633CDB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {323055CB-BF62-4A31-A619-A4444B633CDB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {323055CB-BF62-4A31-A619-A4444B633CDB}.Release|Any CPU.Build.0 = Release|Any CPU {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Debug|Any CPU.Build.0 = Debug|Any CPU {86FFAE3C-648F-4CDE-A260-37C8EBFBF4F2}.Release|Any CPU.ActiveCfg = Release|Any CPU From 0afceb40f59d3306235e2ecd319f187ca8338648 Mon Sep 17 00:00:00 2001 From: geffzhang <136590076@qq.com> Date: Wed, 30 Jan 2019 08:04:48 +0800 Subject: [PATCH 10/19] fix: use http --- src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs | 7 +------ .../Kubernetes/KubeServiceDiscoveryProviderTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs b/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs index d206a6c7..80772167 100644 --- a/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs +++ b/src/Ocelot.Provider.Kubernetes/OcelotBuilderExtensions.cs @@ -1,10 +1,5 @@ -using KubeClient; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; -using Ocelot.ServiceDiscovery; -using System; -using System.Collections.Generic; -using System.Text; namespace Ocelot.Provider.Kubernetes { diff --git a/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs index d0db1507..ccf44fcd 100644 --- a/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs +++ b/test/Ocelot.UnitTests/Kubernetes/KubeServiceDiscoveryProviderTests.cs @@ -37,9 +37,9 @@ namespace Ocelot.UnitTests.Kubernetes { _serviceName = "test"; _namespaces = "dev"; - _port = 8500; + _port = 8001; _kubeHost = "localhost"; - _fakekubeServiceDiscoveryUrl = $"https://{_kubeHost}:{_port}"; + _fakekubeServiceDiscoveryUrl = $"http://{_kubeHost}:{_port}"; _serviceEntries = new ServiceV1(); _factory = new Mock(); _clientFactory = new KubeApiClientFactory(); From 580106aa500dbc4dfa841f5d93626f5663603384 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Wed, 30 Jan 2019 09:32:00 +0800 Subject: [PATCH 11/19] add PollingKubeServiceDiscovery --- .../KubernetesProviderFactory.cs | 4 + src/Ocelot.Provider.Kubernetes/PollKube.cs | 50 +++++++++++ ...ollingKubeServiceDiscoveryProviderTests.cs | 82 +++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 src/Ocelot.Provider.Kubernetes/PollKube.cs create mode 100644 test/Ocelot.UnitTests/Kubernetes/PollingKubeServiceDiscoveryProviderTests.cs diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 34561e0a..7abd7805 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -33,6 +33,10 @@ namespace Ocelot.Provider.Kubernetes var k8sServiceDiscoveryProvider = new Kube(k8sRegistryConfiguration, factory, kubeClientFactory); + if (config.Type?.ToLower() == "pollkube") + { + return new PollKube(config.PollingInterval, factory, k8sServiceDiscoveryProvider); + } return k8sServiceDiscoveryProvider; } } diff --git a/src/Ocelot.Provider.Kubernetes/PollKube.cs b/src/Ocelot.Provider.Kubernetes/PollKube.cs new file mode 100644 index 00000000..a2096e9e --- /dev/null +++ b/src/Ocelot.Provider.Kubernetes/PollKube.cs @@ -0,0 +1,50 @@ +using Ocelot.Logging; +using Ocelot.ServiceDiscovery.Providers; +using Ocelot.Values; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Ocelot.Provider.Kubernetes +{ + public class PollKube : IServiceDiscoveryProvider + { + private readonly IOcelotLogger _logger; + private readonly IServiceDiscoveryProvider _kubeServiceDiscoveryProvider; + private readonly Timer _timer; + private bool _polling; + private List _services; + + public PollKube(int pollingInterval, IOcelotLoggerFactory factory, IServiceDiscoveryProvider kubeServiceDiscoveryProvider) + { + _logger = factory.CreateLogger(); + _kubeServiceDiscoveryProvider = kubeServiceDiscoveryProvider; + _services = new List(); + + _timer = new Timer(async x => + { + if (_polling) + { + return; + } + + _polling = true; + await Poll(); + _polling = false; + }, null, pollingInterval, pollingInterval); + } + + public Task> Get() + { + return Task.FromResult(_services); + } + + private async Task Poll() + { + _services = await _kubeServiceDiscoveryProvider.Get(); + } + } +} + diff --git a/test/Ocelot.UnitTests/Kubernetes/PollingKubeServiceDiscoveryProviderTests.cs b/test/Ocelot.UnitTests/Kubernetes/PollingKubeServiceDiscoveryProviderTests.cs new file mode 100644 index 00000000..49f63afe --- /dev/null +++ b/test/Ocelot.UnitTests/Kubernetes/PollingKubeServiceDiscoveryProviderTests.cs @@ -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 _services; + private readonly Mock _factory; + private readonly Mock _logger; + private readonly Mock _kubeServiceDiscoveryProvider; + private List _result; + + public PollingKubeServiceDiscoveryProviderTests() + { + _services = new List(); + _delay = 1; + _factory = new Mock(); + _logger = new Mock(); + _factory.Setup(x => x.CreateLogger()).Returns(_logger.Object); + _kubeServiceDiscoveryProvider = new Mock(); + } + + [Fact] + public void should_return_service_from_kube() + { + var service = new Service("", new ServiceHostAndPort("", 0), "", "", new List()); + + 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(); + } + } +} From 66e05b1fd782f04919eced7a22e9f2363326ea09 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Wed, 30 Jan 2019 09:39:41 +0800 Subject: [PATCH 12/19] feat : refactor logger --- src/Ocelot.Provider.Kubernetes/KubeProvider.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs index 4492fb09..408df323 100644 --- a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs +++ b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs @@ -25,13 +25,16 @@ namespace Ocelot.Provider.Kubernetes public async Task> Get() { - logger.LogDebug($"namespace:{kubeRegistryConfiguration.KubeNamespace } service:{kubeRegistryConfiguration.KeyOfServiceInK8s}"); - var service = await kubeApi.ServicesV1().Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); + var service = await kubeApi.ServicesV1().Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); var services = new List(); if (IsValid(service)) { services.Add(BuildService(service)); } + else + { + logger.LogWarning($"namespace:{kubeRegistryConfiguration.KubeNamespace }service:{kubeRegistryConfiguration.KeyOfServiceInK8s} Unable to use ,it is invalid. Address must contain host only e.g. localhost and port must be greater than 0"); + } return services; } From 246f2046b38593cca14bec49ab03839cb4ad6f66 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Wed, 30 Jan 2019 09:50:54 +0800 Subject: [PATCH 13/19] feat : add pollkube docs --- docs/features/kubernetes.rst | 23 +++++++++++-------- .../KubernetesProviderFactory.cs | 8 +++---- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/docs/features/kubernetes.rst b/docs/features/kubernetes.rst index 30b57a9b..df393b5a 100644 --- a/docs/features/kubernetes.rst +++ b/docs/features/kubernetes.rst @@ -31,18 +31,10 @@ The example below is taken from the samples folder so please check it if this do "DownstreamScheme": "http", "UpstreamPathTemplate": "/values", "ServiceName": "downstreamservice", - "UpstreamHttpMethod": [ "Get" ], - "QoSOptions": { - "ExceptionsAllowedBeforeBreaking": 3, - "DurationOfBreak": 10000, - "TimeoutValue": 5000 - }, - "FileCacheOptions": { "TtlSeconds": 15 } + "UpstreamHttpMethod": [ "Get" ] } ], "GlobalConfiguration": { - "RequestIdKey": "OcRequestId", - "AdministrationPath": "/administration", "ServiceDiscoveryProvider": { "Host": "192.168.0.13", "Port": 443, @@ -53,4 +45,17 @@ The example below is taken from the samples folder so please check it if this do } } +You also can use Ocelot polls kubernetes for latest service information rather than per request. If you want to poll kubernetes for the latest services rather than per request (default behaviour) then you need to set the following configuration. + +"ServiceDiscoveryProvider": { + "Host": "192.168.0.13", + "Port": 443, + "Token": "txpc696iUhbVoudg164r93CxDTrKRVWG", + "Namespace": "dev", + "Type": "pollkube" + "PollingInterval": 100 +} +The polling interval is in milliseconds and tells Ocelot how often to call kubernetes for changes in service configuration. + +Please note there are tradeoffs here. If you poll kubernetes it is possible Ocelot will not know if a service is down depending on your polling interval and you might get more errors than if you get the latest services per request. This really depends on how volatile your services are. I doubt it will matter for most people and polling may give a tiny performance improvement over calling kubernetes per request. There is no way for Ocelot to work these out for you. diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 7abd7805..735e1116 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -11,11 +11,9 @@ namespace Ocelot.Provider.Kubernetes public static ServiceDiscoveryFinderDelegate Get = (provider, config, name) => { var factory = provider.GetService(); - if (config.Type?.ToLower() == "kube") - { - return GetkubeProvider(provider, config, name, factory); - } - return null; + + return GetkubeProvider(provider, config, name, factory); + }; private static ServiceDiscovery.Providers.IServiceDiscoveryProvider GetkubeProvider(IServiceProvider provider, Configuration.ServiceProviderConfiguration config, string name, IOcelotLoggerFactory factory) From a92dfca36de13930c5ec504fffe0e84f9a54ce27 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Thu, 31 Jan 2019 07:30:27 +0800 Subject: [PATCH 14/19] =?UTF-8?q?feat=EF=BC=9ARemove=20unnecessary=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/features/kubernetes.rst | 5 ++--- samples/OelotKube/ApiGateway/Dockerfile | 1 - samples/OelotKube/ApiGateway/ocelot.json | 2 -- src/Ocelot.Provider.Kubernetes/KubeProvider.cs | 3 ++- .../KubernetesProviderFactory.cs | 7 ++----- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/features/kubernetes.rst b/docs/features/kubernetes.rst index df393b5a..79df38c8 100644 --- a/docs/features/kubernetes.rst +++ b/docs/features/kubernetes.rst @@ -18,9 +18,8 @@ If you have services deployed in kubernetes you will normally use the naming ser The following example shows how to set up a ReRoute that will work in kubernetes. The most important thing is the ServiceName which is made up of the kubernetes service name. We also need to set up the ServiceDiscoveryProvider in -GlobalConfiguration. The example here shows a typical configuration. It assumes kubernetes api server is running on 192.168.0.13 and that the api service is on port 443. +GlobalConfiguration. The example here shows a typical configuration. It assumes kubernetes api server is running on 192.168.0.13 and that api service is on port 443. -The example below is taken from the samples folder so please check it if this doesnt make sense! .. code-block:: json @@ -45,7 +44,7 @@ The example below is taken from the samples folder so please check it if this do } } -You also can use Ocelot polls kubernetes for latest service information rather than per request. If you want to poll kubernetes for the latest services rather than per request (default behaviour) then you need to set the following configuration. +You use Ocelot to poll kubernetes for latest service information rather than per request. If you want to poll kubernetes for the latest services rather than per request (default behaviour) then you need to set the following configuration. "ServiceDiscoveryProvider": { "Host": "192.168.0.13", diff --git a/samples/OelotKube/ApiGateway/Dockerfile b/samples/OelotKube/ApiGateway/Dockerfile index 1ec13d2a..19bd33c2 100644 --- a/samples/OelotKube/ApiGateway/Dockerfile +++ b/samples/OelotKube/ApiGateway/Dockerfile @@ -5,7 +5,6 @@ EXPOSE 80 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY ["ApiGateway/ApiGateway.csproj", "ApiGateway/"] -COPY ["../../src/Ocelot.Provider.Polly/Ocelot.Provider.Polly.csproj", "../../src/Ocelot.Provider.Polly/"] COPY ["../../src/Ocelot/Ocelot.csproj", "../../src/Ocelot/"] COPY ["../../src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj", "../../src/Ocelot.Provider.Kubernetes/"] RUN dotnet restore "ApiGateway/ApiGateway.csproj" diff --git a/samples/OelotKube/ApiGateway/ocelot.json b/samples/OelotKube/ApiGateway/ocelot.json index efe3f36f..ec70503e 100644 --- a/samples/OelotKube/ApiGateway/ocelot.json +++ b/samples/OelotKube/ApiGateway/ocelot.json @@ -9,8 +9,6 @@ } ], "GlobalConfiguration": { - "RequestIdKey": "OcRequestId", - "AdministrationPath": "/administration", "ServiceDiscoveryProvider": { "Host": "192.168.0.13", "Port": 443, diff --git a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs index 408df323..0d1f0fc4 100644 --- a/src/Ocelot.Provider.Kubernetes/KubeProvider.cs +++ b/src/Ocelot.Provider.Kubernetes/KubeProvider.cs @@ -25,7 +25,8 @@ namespace Ocelot.Provider.Kubernetes public async Task> Get() { - var service = await kubeApi.ServicesV1().Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); + var service = await kubeApi.ServicesV1() + .Get(kubeRegistryConfiguration.KeyOfServiceInK8s, kubeRegistryConfiguration.KubeNamespace); var services = new List(); if (IsValid(service)) { diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 735e1116..0de5e389 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -10,10 +10,8 @@ namespace Ocelot.Provider.Kubernetes { public static ServiceDiscoveryFinderDelegate Get = (provider, config, name) => { - var factory = provider.GetService(); - - return GetkubeProvider(provider, config, name, factory); - + var factory = provider.GetService(); + return GetkubeProvider(provider, config, name, factory); }; private static ServiceDiscovery.Providers.IServiceDiscoveryProvider GetkubeProvider(IServiceProvider provider, Configuration.ServiceProviderConfiguration config, string name, IOcelotLoggerFactory factory) @@ -30,7 +28,6 @@ namespace Ocelot.Provider.Kubernetes }; var k8sServiceDiscoveryProvider = new Kube(k8sRegistryConfiguration, factory, kubeClientFactory); - if (config.Type?.ToLower() == "pollkube") { return new PollKube(config.PollingInterval, factory, k8sServiceDiscoveryProvider); From 0ec296fe62b4911664b3795d4657d4b9e3c3a9ad Mon Sep 17 00:00:00 2001 From: geffzhang Date: Thu, 31 Jan 2019 07:31:48 +0800 Subject: [PATCH 15/19] =?UTF-8?q?feat=20=EF=BC=9A=20code-block=20json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/features/kubernetes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/features/kubernetes.rst b/docs/features/kubernetes.rst index 79df38c8..289bb211 100644 --- a/docs/features/kubernetes.rst +++ b/docs/features/kubernetes.rst @@ -46,6 +46,8 @@ GlobalConfiguration. The example here shows a typical configuration. It assumes You use Ocelot to poll kubernetes for latest service information rather than per request. If you want to poll kubernetes for the latest services rather than per request (default behaviour) then you need to set the following configuration. +.. code-block:: json + "ServiceDiscoveryProvider": { "Host": "192.168.0.13", "Port": 443, @@ -54,6 +56,7 @@ You use Ocelot to poll kubernetes for latest service information rather than per "Type": "pollkube" "PollingInterval": 100 } + The polling interval is in milliseconds and tells Ocelot how often to call kubernetes for changes in service configuration. Please note there are tradeoffs here. If you poll kubernetes it is possible Ocelot will not know if a service is down depending on your polling interval and you might get more errors than if you get the latest services per request. This really depends on how volatile your services are. I doubt it will matter for most people and polling may give a tiny performance improvement over calling kubernetes per request. From dae01cb9620718973d18fdb208cb7941a645a196 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Mon, 11 Mar 2019 09:52:05 +0800 Subject: [PATCH 16/19] =?UTF-8?q?feat=EF=BC=9A=20publish=20package=20Ocelo?= =?UTF-8?q?t.Provider.Kubernetes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Ocelot.Provider.Kubernetes.csproj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj index 7a82d52f..a9c43364 100644 --- a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj +++ b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj @@ -2,6 +2,16 @@ netstandard2.0 + true + 0.0.0-dev + geffzhang + + Ocelot + Provides Ocelot extensions to use kubernetes + https://github.com/ThreeMammals/Ocelot + http://threemammals.com/images/ocelot_logo.png + + API Gateway;.NET core From 41c7f8a7e3e4d8cc51a1b2188cb80275dafa6197 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 12 Mar 2019 08:42:49 +0800 Subject: [PATCH 17/19] feat : nuget package --- .../Ocelot.Provider.Kubernetes.csproj | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj index a9c43364..adc4433c 100644 --- a/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj +++ b/src/Ocelot.Provider.Kubernetes/Ocelot.Provider.Kubernetes.csproj @@ -1,17 +1,27 @@ - + netstandard2.0 - true - 0.0.0-dev - geffzhang - + 2.0.0 + 2.0.0 + true Ocelot Provides Ocelot extensions to use kubernetes https://github.com/ThreeMammals/Ocelot http://threemammals.com/images/ocelot_logo.png + Ocelot.Provider.Kubernetes + Ocelot.Provider.Kubernetes API Gateway;.NET core + win10-x64;osx.10.11-x64;osx.10.12-x64;win7-x64 + false + false + True + false + 0.0.0-dev + geffzhang + + ..\..\codeanalysis.ruleset From 4b8f83eb653184988fadeb50139a87767e26af30 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 12 Mar 2019 10:19:21 +0800 Subject: [PATCH 18/19] =?UTF-8?q?fix=EF=BC=9A=20Namesapce=20Spelling=20wro?= =?UTF-8?q?ng?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs | 2 +- .../Builder/ServiceProviderConfigurationBuilder.cs | 4 ++-- .../Creator/ServiceProviderConfigurationCreator.cs | 4 ++-- src/Ocelot/Configuration/ServiceProviderConfiguration.cs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs index 0de5e389..30ed2c85 100644 --- a/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs +++ b/src/Ocelot.Provider.Kubernetes/KubernetesProviderFactory.cs @@ -21,7 +21,7 @@ namespace Ocelot.Provider.Kubernetes { ApiEndPoint = new Uri($"https://{config.Host}:{config.Port}"), KeyOfServiceInK8s = name, - KubeNamespace = config.Namesapce, + KubeNamespace = config.Namespace, AuthStrategy = KubeAuthStrategy.BearerToken, AccessToken = config.Token, AllowInsecure = true // Don't validate server certificate diff --git a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs index e9cc947f..16ec15d0 100644 --- a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs @@ -46,9 +46,9 @@ namespace Ocelot.Configuration.Builder return this; } - public ServiceProviderConfigurationBuilder WithNamesapce(string @namesapce) + public ServiceProviderConfigurationBuilder WithNamespace(string @namespace) { - _namespace = @namesapce; + _namespace = @namespace; return this; } diff --git a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs index 88137a8b..3b0ee225 100644 --- a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs @@ -13,7 +13,7 @@ namespace Ocelot.Configuration.Creator ? globalConfiguration?.ServiceDiscoveryProvider?.Type : "consul"; var pollingInterval = globalConfiguration?.ServiceDiscoveryProvider?.PollingInterval ?? 0; - var k8snamesapce = globalConfiguration?.ServiceDiscoveryProvider?.Namespace ?? string.Empty; + var k8snamespace = globalConfiguration?.ServiceDiscoveryProvider?.Namespace ?? string.Empty; return new ServiceProviderConfigurationBuilder() .WithHost(host) @@ -22,7 +22,7 @@ namespace Ocelot.Configuration.Creator .WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token) .WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey) .WithPollingInterval(pollingInterval) - .WithNamesapce(k8snamesapce) + .WithNamespace(k8snamespace) .Build(); } } diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguration.cs b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs index 05ee07d4..86178c6e 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguration.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguration.cs @@ -10,7 +10,7 @@ Token = token; Type = type; PollingInterval = pollingInterval; - Namesapce = @namespace; + Namespace = @namespace; } public string Host { get; } @@ -25,6 +25,6 @@ public int PollingInterval { get; } - public string Namesapce { get; } + public string Namespace { get; } } } From 7db67f4e368343c551d823a047ea68b4302b16b7 Mon Sep 17 00:00:00 2001 From: geffzhang Date: Tue, 12 Mar 2019 10:25:49 +0800 Subject: [PATCH 19/19] =?UTF-8?q?fix=EF=BC=9ANamesapce=20Spelling=20Wrong?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configuration/ServiceProviderCreatorTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs index fcf0c52a..2094a172 100644 --- a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs @@ -41,7 +41,7 @@ namespace Ocelot.UnitTests.Configuration .WithType("ServiceFabric") .WithToken("testtoken") .WithConfigurationKey("woo") - .WithNamesapce("default") + .WithNamespace("default") .Build(); this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig)) @@ -66,7 +66,7 @@ namespace Ocelot.UnitTests.Configuration _result.Port.ShouldBe(expected.Port); _result.Token.ShouldBe(expected.Token); _result.Type.ShouldBe(expected.Type); - _result.Namesapce.ShouldBe(expected.Namesapce); + _result.Namespace.ShouldBe(expected.Namespace); _result.ConfigurationKey.ShouldBe(expected.ConfigurationKey); } }