diff --git a/global.json b/global.json index 332404a7..9a3e328e 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "projects": [ "src", "test" ], "sdk": { - "version": "2.0.0" + "version": "2.0.2" } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs index 272242c8..b823e6ac 100644 --- a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs @@ -26,13 +26,14 @@ namespace Ocelot.Configuration.Builder private string _downstreamHost; private int _downstreamPort; private string _loadBalancer; - private ServiceProviderConfiguration _serviceProviderConfiguraion; private bool _useQos; private QoSOptions _qosOptions; private HttpHandlerOptions _httpHandlerOptions; public bool _enableRateLimiting; public RateLimitOptions _rateLimitOptions; private string _authenticationProviderKey; + private bool _useServiceDiscovery; + private string _serviceName; public ReRouteBuilder WithLoadBalancer(string loadBalancer) { @@ -154,12 +155,6 @@ namespace Ocelot.Configuration.Builder return this; } - public ReRouteBuilder WithServiceProviderConfiguraion(ServiceProviderConfiguration serviceProviderConfiguraion) - { - _serviceProviderConfiguraion = serviceProviderConfiguraion; - return this; - } - public ReRouteBuilder WithAuthenticationOptions(AuthenticationOptions authenticationOptions) { _authenticationOptions = authenticationOptions; @@ -190,6 +185,18 @@ namespace Ocelot.Configuration.Builder return this; } + public ReRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery) + { + _useServiceDiscovery = useServiceDiscovery; + return this; + } + + public ReRouteBuilder WithServiceName(string serviceName) + { + _serviceName = serviceName; + return this; + } + public ReRoute Build() { return new ReRoute( @@ -212,12 +219,13 @@ namespace Ocelot.Configuration.Builder _downstreamHost, _downstreamPort, _loadBalancerKey, - _serviceProviderConfiguraion, _useQos, _qosOptions, _enableRateLimiting, _rateLimitOptions, - _httpHandlerOptions); + _httpHandlerOptions, + _useServiceDiscovery, + _serviceName); } } } diff --git a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs index cb3c521c..fe9f7f3c 100644 --- a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs @@ -2,38 +2,10 @@ namespace Ocelot.Configuration.Builder { public class ServiceProviderConfigurationBuilder { - private string _serviceName; - private string _downstreamHost; - private int _downstreamPort; - private bool _userServiceDiscovery; private string _serviceDiscoveryProvider; private string _serviceDiscoveryProviderHost; private int _serviceDiscoveryProviderPort; - public ServiceProviderConfigurationBuilder WithServiceName(string serviceName) - { - _serviceName = serviceName; - return this; - } - - public ServiceProviderConfigurationBuilder WithDownstreamHost(string downstreamHost) - { - _downstreamHost = downstreamHost; - return this; - } - - public ServiceProviderConfigurationBuilder WithDownstreamPort(int downstreamPort) - { - _downstreamPort = downstreamPort; - return this; - } - - public ServiceProviderConfigurationBuilder WithUseServiceDiscovery(bool userServiceDiscovery) - { - _userServiceDiscovery = userServiceDiscovery; - return this; - } - public ServiceProviderConfigurationBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider) { _serviceDiscoveryProvider = serviceDiscoveryProvider; @@ -52,11 +24,9 @@ namespace Ocelot.Configuration.Builder return this; } - public ServiceProviderConfiguration Build() { - return new ServiceProviderConfiguration(_serviceName, _downstreamHost, _downstreamPort, _userServiceDiscovery, - _serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort); + return new ServiceProviderConfiguration(_serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort); } } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs index fd27e4e6..5a5bb607 100644 --- a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs @@ -26,7 +26,6 @@ namespace Ocelot.Configuration.Creator private readonly IOptions _options; private readonly IConfigurationValidator _configurationValidator; private readonly IOcelotLogger _logger; - private readonly ILoadBalancerCreator _lbCreator; private readonly IQoSProviderFactory _qoSProviderFactory; private readonly IQosProviderHouse _qosProviderHouse; private readonly IClaimsToThingCreator _claimsToThingCreator; @@ -44,7 +43,6 @@ namespace Ocelot.Configuration.Creator IOptions options, IConfigurationValidator configurationValidator, IOcelotLoggerFactory loggerFactory, - ILoadBalancerCreator lbCreator, IQoSProviderFactory qoSProviderFactory, IQosProviderHouse qosProviderHouse, IClaimsToThingCreator claimsToThingCreator, @@ -59,7 +57,6 @@ namespace Ocelot.Configuration.Creator IHttpHandlerOptionsCreator httpHandlerOptionsCreator ) { - _lbCreator = lbCreator; _regionCreator = regionCreator; _rateLimitOptionsCreator = rateLimitOptionsCreator; _requestIdKeyCreator = requestIdKeyCreator; @@ -114,8 +111,10 @@ namespace Ocelot.Configuration.Creator var ocelotReRoute = await SetUpReRoute(reRoute, fileConfiguration.GlobalConfiguration); reRoutes.Add(ocelotReRoute); } + + var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration); - return new OcelotConfiguration(reRoutes, fileConfiguration.GlobalConfiguration.AdministrationPath); + return new OcelotConfiguration(reRoutes, fileConfiguration.GlobalConfiguration.AdministrationPath, serviceProviderConfiguration); } private async Task SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) @@ -128,8 +127,6 @@ namespace Ocelot.Configuration.Creator var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute); - var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileReRoute, globalConfiguration); - var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute); var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest); @@ -166,7 +163,6 @@ namespace Ocelot.Configuration.Creator .WithDownstreamHost(fileReRoute.DownstreamHost) .WithDownstreamPort(fileReRoute.DownstreamPort) .WithLoadBalancerKey(reRouteKey) - .WithServiceProviderConfiguraion(serviceProviderConfiguration) .WithIsQos(fileReRouteOptions.IsQos) .WithQosOptions(qosOptions) .WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting) @@ -174,7 +170,6 @@ namespace Ocelot.Configuration.Creator .WithHttpHandlerOptions(httpHandlerOptions) .Build(); - await _lbCreator.SetupLoadBalancer(reRoute); SetupQosProvider(reRoute); return reRoute; } diff --git a/src/Ocelot/Configuration/Creator/IServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/IServiceProviderConfigurationCreator.cs index 1c03d893..ea48ba54 100644 --- a/src/Ocelot/Configuration/Creator/IServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/IServiceProviderConfigurationCreator.cs @@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator { public interface IServiceProviderConfigurationCreator { - ServiceProviderConfiguration Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration); + ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration); } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs index 8132d021..a29e285c 100644 --- a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs @@ -5,18 +5,11 @@ namespace Ocelot.Configuration.Creator { public class ServiceProviderConfigurationCreator : IServiceProviderConfigurationCreator { - public ServiceProviderConfiguration Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) + public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration) { - var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName) - && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider); - var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0; return new ServiceProviderConfigurationBuilder() - .WithServiceName(fileReRoute.ServiceName) - .WithDownstreamHost(fileReRoute.DownstreamHost) - .WithDownstreamPort(fileReRoute.DownstreamPort) - .WithUseServiceDiscovery(useServiceDiscovery) .WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider) .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) .WithServiceDiscoveryProviderPort(serviceProviderPort) diff --git a/src/Ocelot/Configuration/IOcelotConfiguration.cs b/src/Ocelot/Configuration/IOcelotConfiguration.cs index 566e2f91..cb1ff606 100644 --- a/src/Ocelot/Configuration/IOcelotConfiguration.cs +++ b/src/Ocelot/Configuration/IOcelotConfiguration.cs @@ -6,5 +6,6 @@ namespace Ocelot.Configuration { List ReRoutes { get; } string AdministrationPath {get;} + ServiceProviderConfiguration ServiceProviderConfiguration {get;} } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/OcelotConfiguration.cs b/src/Ocelot/Configuration/OcelotConfiguration.cs index 5655b3c2..b4f5d169 100644 --- a/src/Ocelot/Configuration/OcelotConfiguration.cs +++ b/src/Ocelot/Configuration/OcelotConfiguration.cs @@ -4,13 +4,15 @@ namespace Ocelot.Configuration { public class OcelotConfiguration : IOcelotConfiguration { - public OcelotConfiguration(List reRoutes, string administrationPath) + public OcelotConfiguration(List reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration) { ReRoutes = reRoutes; AdministrationPath = administrationPath; + ServiceProviderConfiguration = serviceProviderConfiguration; } public List ReRoutes { get; } public string AdministrationPath {get;} + public ServiceProviderConfiguration ServiceProviderConfiguration {get;} } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/ReRoute.cs b/src/Ocelot/Configuration/ReRoute.cs index cfc8b9ba..57f8fcc5 100644 --- a/src/Ocelot/Configuration/ReRoute.cs +++ b/src/Ocelot/Configuration/ReRoute.cs @@ -25,15 +25,17 @@ namespace Ocelot.Configuration string downstreamHost, int downstreamPort, string reRouteKey, - ServiceProviderConfiguration serviceProviderConfiguraion, bool isQos, QoSOptions qosOptions, bool enableEndpointRateLimiting, RateLimitOptions ratelimitOptions, - HttpHandlerOptions httpHandlerOptions) + HttpHandlerOptions httpHandlerOptions, + bool useServiceDiscovery, + string serviceName) { + ServiceName = serviceName; + UseServiceDiscovery = useServiceDiscovery; ReRouteKey = reRouteKey; - ServiceProviderConfiguraion = serviceProviderConfiguraion; LoadBalancer = loadBalancer; DownstreamHost = downstreamHost; DownstreamPort = downstreamPort; @@ -83,9 +85,10 @@ namespace Ocelot.Configuration public string LoadBalancer {get;private set;} public string DownstreamHost { get; private set; } public int DownstreamPort { get; private set; } - public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; } public bool EnableEndpointEndpointRateLimiting { get; private set; } public RateLimitOptions RateLimitOptions { get; private set; } public HttpHandlerOptions HttpHandlerOptions { get; private set; } + public bool UseServiceDiscovery {get;private set;} + public string ServiceName {get;private set;} } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs index 664fa4c3..46351044 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs @@ -2,22 +2,13 @@ { public class ServiceProviderConfiguration { - public ServiceProviderConfiguration(string serviceName, string downstreamHost, - int downstreamPort, bool useServiceDiscovery, string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort) + public ServiceProviderConfiguration(string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort) { - ServiceName = serviceName; - DownstreamHost = downstreamHost; - DownstreamPort = downstreamPort; - UseServiceDiscovery = useServiceDiscovery; ServiceDiscoveryProvider = serviceDiscoveryProvider; ServiceProviderHost = serviceProviderHost; ServiceProviderPort = serviceProviderPort; } - public string ServiceName { get; } - public string DownstreamHost { get; } - public int DownstreamPort { get; } - public bool UseServiceDiscovery { get; } public string ServiceDiscoveryProvider { get; } public string ServiceProviderHost { get; private set; } public int ServiceProviderPort { get; private set; } diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index 85f0f4b6..33f6dabb 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -94,7 +94,6 @@ namespace Ocelot.DependencyInjection .AddJsonFormatters(); services.AddLogging(); - services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/src/Ocelot/LoadBalancer/ILoadBalancerCreator.cs b/src/Ocelot/LoadBalancer/ILoadBalancerCreator.cs deleted file mode 100644 index e60c36f0..00000000 --- a/src/Ocelot/LoadBalancer/ILoadBalancerCreator.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration; - -namespace Ocelot.LoadBalancer -{ - public interface ILoadBalancerCreator - { - Task SetupLoadBalancer(ReRoute reRoute); - } -} \ No newline at end of file diff --git a/src/Ocelot/LoadBalancer/LoadBalancerCreator.cs b/src/Ocelot/LoadBalancer/LoadBalancerCreator.cs deleted file mode 100644 index da28e5b8..00000000 --- a/src/Ocelot/LoadBalancer/LoadBalancerCreator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration; -using Ocelot.LoadBalancer.LoadBalancers; - -namespace Ocelot.LoadBalancer -{ - public class LoadBalancerCreator : ILoadBalancerCreator - { - private readonly ILoadBalancerHouse _loadBalancerHouse; - private readonly ILoadBalancerFactory _loadBalanceFactory; - - public LoadBalancerCreator(ILoadBalancerHouse loadBalancerHouse, ILoadBalancerFactory loadBalancerFactory) - { - _loadBalancerHouse = loadBalancerHouse; - _loadBalanceFactory = loadBalancerFactory; - } - - public async Task SetupLoadBalancer(ReRoute reRoute) - { - var loadBalancer = await _loadBalanceFactory.Get(reRoute); - _loadBalancerHouse.Add(reRoute.ReRouteKey, loadBalancer); - } - } -} \ No newline at end of file diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs index 19fdf3eb..cc7bc6a6 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs @@ -5,6 +5,6 @@ namespace Ocelot.LoadBalancer.LoadBalancers { public interface ILoadBalancerFactory { - Task Get(ReRoute reRoute); + Task Get(ReRoute reRoute, ServiceProviderConfiguration config); } } \ No newline at end of file diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerHouse.cs b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerHouse.cs index 065ae2ac..558861cf 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerHouse.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerHouse.cs @@ -1,10 +1,11 @@ -using Ocelot.Responses; +using System.Threading.Tasks; +using Ocelot.Configuration; +using Ocelot.Responses; namespace Ocelot.LoadBalancer.LoadBalancers { public interface ILoadBalancerHouse { - Response Get(string key); - Response Add(string key, ILoadBalancer loadBalancer); + Task> Get(ReRoute reRoute, ServiceProviderConfiguration config); } } \ No newline at end of file diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs index e7b323a4..596a1c22 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs @@ -12,16 +12,16 @@ namespace Ocelot.LoadBalancer.LoadBalancers _serviceProviderFactory = serviceProviderFactory; } - public async Task Get(ReRoute reRoute) + public async Task Get(ReRoute reRoute, ServiceProviderConfiguration config) { - var serviceProvider = _serviceProviderFactory.Get(reRoute.ServiceProviderConfiguraion); + var serviceProvider = _serviceProviderFactory.Get(config, reRoute); switch (reRoute.LoadBalancer) { case "RoundRobin": return new RoundRobinLoadBalancer(async () => await serviceProvider.Get()); case "LeastConnection": - return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceProviderConfiguraion.ServiceName); + return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceName); default: return new NoLoadBalancer(await serviceProvider.Get()); } diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs index 68e42fe2..01d530af 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs @@ -1,33 +1,58 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ocelot.Configuration; using Ocelot.Responses; namespace Ocelot.LoadBalancer.LoadBalancers { public class LoadBalancerHouse : ILoadBalancerHouse { + private readonly ILoadBalancerFactory _factory; private readonly Dictionary _loadBalancers; - public LoadBalancerHouse() + public LoadBalancerHouse(ILoadBalancerFactory factory) { + _factory = factory; _loadBalancers = new Dictionary(); } - public Response Get(string key) + public async Task> Get(ReRoute reRoute, ServiceProviderConfiguration config) { - ILoadBalancer loadBalancer; - - if(_loadBalancers.TryGetValue(key, out loadBalancer)) + try { - return new OkResponse(_loadBalancers[key]); + ILoadBalancer loadBalancer; + + if(_loadBalancers.TryGetValue(reRoute.ReRouteKey, out loadBalancer)) + { + loadBalancer = _loadBalancers[reRoute.ReRouteKey]; + + //todo - we have some duplicate namey type logic in the LoadBalancerFactory...maybe we can do something + //about this.. + if((reRoute.LoadBalancer == "RoundRobin" && loadBalancer.GetType() != typeof(RoundRobinLoadBalancer)) + || (reRoute.LoadBalancer == "LeastConnection" && loadBalancer.GetType() != typeof(LeastConnectionLoadBalancer))) + { + loadBalancer = await _factory.Get(reRoute, config); + AddLoadBalancer(reRoute.ReRouteKey, loadBalancer); + } + + return new OkResponse(loadBalancer); + } + + loadBalancer = await _factory.Get(reRoute, config); + AddLoadBalancer(reRoute.ReRouteKey, loadBalancer); + return new OkResponse(loadBalancer); } - - return new ErrorResponse(new List() + catch(Exception ex) { - new UnableToFindLoadBalancerError($"unabe to find load balancer for {key}") - }); + return new ErrorResponse(new List() + { + new UnableToFindLoadBalancerError($"unabe to find load balancer for {reRoute.ReRouteKey} exception is {ex}") + }); + } } - public Response Add(string key, ILoadBalancer loadBalancer) + private void AddLoadBalancer(string key, ILoadBalancer loadBalancer) { if (!_loadBalancers.ContainsKey(key)) { @@ -36,7 +61,6 @@ namespace Ocelot.LoadBalancer.LoadBalancers _loadBalancers.Remove(key); _loadBalancers.Add(key, loadBalancer); - return new OkResponse(); } } } diff --git a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs index 909ef755..079f3584 100644 --- a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs +++ b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Ocelot.Configuration.Provider; using Ocelot.Infrastructure.RequestData; using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.Logging; @@ -11,6 +12,7 @@ namespace Ocelot.LoadBalancer.Middleware { public class LoadBalancingMiddleware : OcelotMiddleware { + private readonly IOcelotConfigurationProvider _configProvider; private readonly RequestDelegate _next; private readonly IOcelotLogger _logger; private readonly ILoadBalancerHouse _loadBalancerHouse; @@ -18,9 +20,11 @@ namespace Ocelot.LoadBalancer.Middleware public LoadBalancingMiddleware(RequestDelegate next, IOcelotLoggerFactory loggerFactory, IRequestScopedDataRepository requestScopedDataRepository, - ILoadBalancerHouse loadBalancerHouse) + ILoadBalancerHouse loadBalancerHouse, + IOcelotConfigurationProvider configProvider) : base(requestScopedDataRepository) { + _configProvider = configProvider; _next = next; _logger = loggerFactory.CreateLogger(); _loadBalancerHouse = loadBalancerHouse; @@ -28,7 +32,9 @@ namespace Ocelot.LoadBalancer.Middleware public async Task Invoke(HttpContext context) { - var loadBalancer = _loadBalancerHouse.Get(DownstreamRoute.ReRoute.ReRouteKey); + var configuration = await _configProvider.Get(); + + var loadBalancer = await _loadBalancerHouse.Get(DownstreamRoute.ReRoute, configuration.Data.ServiceProviderConfiguration); if(loadBalancer.IsError) { _logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error"); diff --git a/src/Ocelot/ServiceDiscovery/IServiceDiscoveryProviderFactory.cs b/src/Ocelot/ServiceDiscovery/IServiceDiscoveryProviderFactory.cs index 18c88c76..e92d50b0 100644 --- a/src/Ocelot/ServiceDiscovery/IServiceDiscoveryProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/IServiceDiscoveryProviderFactory.cs @@ -4,6 +4,6 @@ namespace Ocelot.ServiceDiscovery { public interface IServiceDiscoveryProviderFactory { - IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig); + IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, ReRoute reRoute); } } \ No newline at end of file diff --git a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs index 49151c01..5dc4982a 100644 --- a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs @@ -6,17 +6,17 @@ namespace Ocelot.ServiceDiscovery { public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory { - public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig) + public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, ReRoute reRoute) { - if (serviceConfig.UseServiceDiscovery) + if (reRoute.UseServiceDiscovery) { - return GetServiceDiscoveryProvider(serviceConfig.ServiceName, serviceConfig.ServiceDiscoveryProvider, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort); + return GetServiceDiscoveryProvider(reRoute.ServiceName, serviceConfig.ServiceDiscoveryProvider, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort); } var services = new List() { - new Service(serviceConfig.ServiceName, - new HostAndPort(serviceConfig.DownstreamHost, serviceConfig.DownstreamPort), + new Service(reRoute.ServiceName, + new HostAndPort(reRoute.DownstreamHost, reRoute.DownstreamPort), string.Empty, string.Empty, new string[0]) diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index 87476533..90db18e3 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.IO; using System.Net; using System.Text; +using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using Ocelot.Configuration; +using Ocelot.Configuration.Builder; using Ocelot.Configuration.File; using Ocelot.ServiceDiscovery; using TestStack.BDDfy; @@ -60,7 +62,7 @@ namespace Ocelot.AcceptanceTests var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot"); this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl)) - .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", 200, "Hello from Laura")) + .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "", 200, "Hello from Laura")) .And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig)) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) @@ -69,6 +71,69 @@ namespace Ocelot.AcceptanceTests .BDDfy(); } + [Fact] + public void should_fix_issue_142() + { + var configuration = new FileConfiguration + { + ReRoutes = new List + { + }, + GlobalConfiguration = new FileGlobalConfiguration() + { + ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() + { + Provider = "Consul", + Host = "localhost", + Port = 9500 + } + } + }; + + var fakeConsulServiceDiscoveryUrl = "http://localhost:9500"; + + var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot"); + + var serviceProviderConfig = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProvider("Consul") + .WithServiceDiscoveryProviderHost("localhost") + .WithServiceDiscoveryProviderPort(8500) + .Build(); + + var reRoute = new ReRouteBuilder() + .WithDownstreamPathTemplate("/status") + .WithUpstreamTemplatePattern("^(?i)/cs/status/$") + .WithDownstreamScheme("http") + .WithDownstreamHost("localhost") + .WithDownstreamPort(51779) + .WithUpstreamPathTemplate("/cs/status") + .WithUpstreamHttpMethod(new List {"Get"}) + .WithLoadBalancer("LeastConnection") + .WithLoadBalancerKey("/cs/status|Get") + .WithServiceName("") + .WithUseServiceDiscovery(true) + .Build(); + + var reRoutes = new List { reRoute }; + + var config = new OcelotConfiguration(reRoutes, null, serviceProviderConfig); + + this.Given(x => GivenTheConsulConfigurationIs(config)) + .And(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl)) + .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "/status", 200, "Hello from Laura")) + .And(x => _steps.GivenThereIsAConfiguration(configuration)) + .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig)) + .When(x => _steps.WhenIGetUrlOnTheApiGateway("/cs/status")) + .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) + .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) + .BDDfy(); + } + + private void GivenTheConsulConfigurationIs(OcelotConfiguration config) + { + _config = config; + } + private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url) { _fakeConsulBuilder = new WebHostBuilder() @@ -137,7 +202,7 @@ namespace Ocelot.AcceptanceTests public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e"; } - private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody) + private void GivenThereIsAServiceRunningOn(string url, string basePath, int statusCode, string responseBody) { _builder = new WebHostBuilder() .UseUrls(url) @@ -147,6 +212,8 @@ namespace Ocelot.AcceptanceTests .UseUrls(url) .Configure(app => { + app.UsePathBase(basePath); + app.Run(async context => { context.Response.StatusCode = statusCode; diff --git a/test/Ocelot.AcceptanceTests/RequestId:0HL9635DF6NNV b/test/Ocelot.AcceptanceTests/RequestId:0HL9635DF6NNV new file mode 100644 index 00000000..e69de29b diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index 0440e7ee..d68bc054 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -44,7 +44,6 @@ namespace Ocelot.UnitTests.Configuration private Mock _rateLimitOptions; private Mock _regionCreator; private Mock _httpHandlerOptionsCreator; - private Mock _lbCreator; public FileConfigurationCreatorTests() { @@ -65,11 +64,9 @@ namespace Ocelot.UnitTests.Configuration _rateLimitOptions = new Mock(); _regionCreator = new Mock(); _httpHandlerOptionsCreator = new Mock(); - _lbCreator = new Mock(); _ocelotConfigurationCreator = new FileOcelotConfigurationCreator( _fileConfig.Object, _validator.Object, _logger.Object, - _lbCreator.Object, _qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object, _authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object, _serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object, @@ -189,32 +186,6 @@ namespace Ocelot.UnitTests.Configuration .BDDfy(); } - [Fact] - public void should_create_load_balancer() - { - var reRouteOptions = new ReRouteOptionsBuilder() - .Build(); - - this.Given(x => x.GivenTheConfigIs(new FileConfiguration - { - ReRoutes = new List - { - new FileReRoute - { - DownstreamHost = "127.0.0.1", - UpstreamPathTemplate = "/api/products/{productId}", - DownstreamPathTemplate = "/products/{productId}", - UpstreamHttpMethod = new List { "Get" }, - } - }, - })) - .And(x => x.GivenTheConfigIsValid()) - .And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions)) - .When(x => x.WhenICreateTheConfig()) - .And(x => x.ThenTheLoadBalancerCreatorIsCalledCorrectly()) - .BDDfy(); - } - [Fact] public void should_use_downstream_host() { @@ -320,12 +291,8 @@ namespace Ocelot.UnitTests.Configuration .WithDownstreamPathTemplate("/products/{productId}") .WithUpstreamPathTemplate("/api/products/{productId}") .WithUpstreamHttpMethod(new List { "Get" }) - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder() - .WithUseServiceDiscovery(true) - .WithServiceDiscoveryProvider("consul") - .WithServiceDiscoveryProviderHost("127.0.0.1") - .WithServiceName("ProductService") - .Build()) + .WithUseServiceDiscovery(true) + .WithServiceName("ProductService") .Build() })) .BDDfy(); @@ -359,9 +326,7 @@ namespace Ocelot.UnitTests.Configuration .WithDownstreamPathTemplate("/products/{productId}") .WithUpstreamPathTemplate("/api/products/{productId}") .WithUpstreamHttpMethod(new List { "Get" }) - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder() - .WithUseServiceDiscovery(false) - .Build()) + .WithUseServiceDiscovery(false) .Build() })) .BDDfy(); @@ -604,20 +569,6 @@ namespace Ocelot.UnitTests.Configuration } } - private void ThenTheServiceConfigurationIs(ServiceProviderConfiguration expected) - { - for (int i = 0; i < _config.Data.ReRoutes.Count; i++) - { - var result = _config.Data.ReRoutes[i]; - result.ServiceProviderConfiguraion.DownstreamHost.ShouldBe(expected.DownstreamHost); - result.ServiceProviderConfiguraion.DownstreamPort.ShouldBe(expected.DownstreamPort); - result.ServiceProviderConfiguraion.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider); - result.ServiceProviderConfiguraion.ServiceName.ShouldBe(expected.ServiceName); - result.ServiceProviderConfiguraion.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost); - result.ServiceProviderConfiguraion.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort); - } - } - private void ThenTheAuthenticationOptionsAre(List expectedReRoutes) { for (int i = 0; i < _config.Data.ReRoutes.Count; i++) @@ -628,11 +579,6 @@ namespace Ocelot.UnitTests.Configuration } } - private void ThenTheLoadBalancerCreatorIsCalledCorrectly() - { - _lbCreator.Verify(x => x.SetupLoadBalancer(It.IsAny()), Times.Once); - } - private void GivenTheQosProviderFactoryReturns() { _qosProviderFactory diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs index bf4804f6..50ab0bc8 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Moq; using Ocelot.Configuration; +using Ocelot.Configuration.Builder; using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; using Ocelot.Configuration.Repository; @@ -36,7 +37,8 @@ namespace Ocelot.UnitTests.Configuration public void should_set_configuration() { var fileConfig = new FileConfiguration(); - var config = new OcelotConfiguration(new List(), string.Empty); + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + var config = new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig); this.Given(x => GivenTheFollowingConfiguration(fileConfig)) .And(x => GivenTheRepoReturns(new OkResponse())) diff --git a/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs b/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs index b65aa095..fa853c7f 100644 --- a/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs @@ -92,6 +92,8 @@ namespace Ocelot.UnitTests.Configuration }; public string AdministrationPath {get;} + + public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException(); } } } diff --git a/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs b/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs index 430844fe..b1a6f314 100644 --- a/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs +++ b/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Moq; using Ocelot.Configuration; +using Ocelot.Configuration.Builder; using Ocelot.Configuration.Creator; using Ocelot.Configuration.Provider; using Ocelot.Configuration.Repository; @@ -27,9 +28,11 @@ namespace Ocelot.UnitTests.Configuration [Fact] public void should_get_config() { - this.Given(x => x.GivenTheRepoReturns(new OkResponse(new OcelotConfiguration(new List(), string.Empty)))) + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + + this.Given(x => x.GivenTheRepoReturns(new OkResponse(new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig)))) .When(x => x.WhenIGetTheConfig()) - .Then(x => x.TheFollowingIsReturned(new OkResponse(new OcelotConfiguration(new List(), string.Empty)))) + .Then(x => x.TheFollowingIsReturned(new OkResponse(new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig)))) .BDDfy(); } diff --git a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs index 8d76e864..8c33b4e5 100644 --- a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs @@ -60,15 +60,12 @@ namespace Ocelot.UnitTests.Configuration private void WhenICreate() { - _result = _creator.Create(_reRoute, _globalConfig); + _result = _creator.Create(_globalConfig); } private void ThenTheConfigIs(ServiceProviderConfiguration expected) { - _result.DownstreamHost.ShouldBe(expected.DownstreamHost); - _result.DownstreamPort.ShouldBe(expected.DownstreamPort); _result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider); - _result.ServiceName.ShouldBe(expected.ServiceName); _result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost); _result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort); } diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index 8dbe6ef4..2ae88eb3 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -36,6 +36,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_return_route() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/")) .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( new OkResponse>( @@ -48,7 +50,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get" }) .WithUpstreamTemplatePattern("someUpstreamPath") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) @@ -69,6 +71,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_append_slash_to_upstream_url_path() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher")) .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( new OkResponse>( @@ -81,7 +85,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get" }) .WithUpstreamTemplatePattern("someUpstreamPath") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) @@ -101,6 +105,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_return_route_if_upstream_path_and_upstream_template_are_the_same() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => @@ -114,7 +120,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get" }) .WithUpstreamTemplatePattern("someUpstreamPath") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) @@ -133,6 +139,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_return_correct_route_for_http_verb() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => @@ -152,7 +160,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Post" }) .WithUpstreamTemplatePattern("") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) @@ -169,7 +177,9 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_not_return_route() - { + { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath/")) .And(x => x.GivenTheConfigurationIs(new List { @@ -179,7 +189,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get" }) .WithUpstreamTemplatePattern("somePath") .Build(), - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(false)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Get")) @@ -193,6 +203,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_return_correct_route_for_http_verb_setting_multiple_upstream_http_method() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => @@ -206,7 +218,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get", "Post" }) .WithUpstreamTemplatePattern("") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) @@ -224,6 +236,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_return_correct_route_for_http_verb_setting_all_upstream_http_method() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => @@ -237,7 +251,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List()) .WithUpstreamTemplatePattern("") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) @@ -255,6 +269,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder [Fact] public void should_not_return_route_for_http_verb_not_setting_in_upstream_http_method() { + var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); + this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) .And( x => @@ -268,7 +284,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .WithUpstreamHttpMethod(new List { "Get", "Patch", "Delete" }) .WithUpstreamTemplatePattern("") .Build() - }, string.Empty + }, string.Empty, serviceProviderConfig )) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse(new UrlMatch(true)))) .And(x => x.GivenTheUpstreamHttpMethodIs("Post")) @@ -322,12 +338,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder .Returns(_match); } - private void GivenTheConfigurationIs(List reRoutesConfig, string adminPath) + private void GivenTheConfigurationIs(List reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig) { _reRoutesConfig = reRoutesConfig; _mockConfig .Setup(x => x.Get()) - .ReturnsAsync(new OkResponse(new OcelotConfiguration(_reRoutesConfig, adminPath))); + .ReturnsAsync(new OkResponse(new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig))); } private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerCreatorTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerCreatorTests.cs deleted file mode 100644 index 9b9a2df1..00000000 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerCreatorTests.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Xunit; -using Shouldly; -using TestStack.BDDfy; -using Ocelot.LoadBalancer; -using Ocelot.LoadBalancer.LoadBalancers; -using Moq; -using Ocelot.Configuration; -using System.Collections.Generic; -using Ocelot.Values; -using Ocelot.Configuration.Builder; - -namespace Ocelot.UnitTests.LoadBalancer -{ - public class LoadBalancerCreatorTests - { - private LoadBalancerCreator _creator; - private ILoadBalancerHouse _house; - private Mock _factory; - private ReRoute _reRoute; - - public LoadBalancerCreatorTests() - { - _house = new LoadBalancerHouse(); - _factory = new Mock(); - _creator = new LoadBalancerCreator(_house, _factory.Object); - } - - [Fact] - public void should_create_load_balancer() - { - var reRoute = new ReRouteBuilder().WithLoadBalancerKey("Test").Build(); - this.Given(x => GivenTheFollowingReRoute(reRoute)) - .When(x => WhenICallTheCreator()) - .Then(x => x.ThenTheLoadBalancerIsCreated()) - .BDDfy(); - } - - private void GivenTheFollowingReRoute(ReRoute reRoute) - { - _reRoute = reRoute; - _factory - .Setup(x => x.Get(It.IsAny())) - .ReturnsAsync(new NoLoadBalancer(new List())); - } - - private void WhenICallTheCreator() - { - _creator.SetupLoadBalancer(_reRoute).Wait(); - } - - private void ThenTheLoadBalancerIsCreated() - { - var lb = _house.Get(_reRoute.ReRouteKey); - lb.ShouldNotBeNull(); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs index ccf97772..9fde2f78 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs @@ -17,7 +17,8 @@ namespace Ocelot.UnitTests.LoadBalancer private ILoadBalancer _result; private Mock _serviceProviderFactory; private Mock _serviceProvider; - + private ServiceProviderConfiguration _serviceProviderConfig; + public LoadBalancerFactoryTests() { _serviceProviderFactory = new Mock(); @@ -29,11 +30,11 @@ namespace Ocelot.UnitTests.LoadBalancer public void should_return_no_load_balancer() { var reRoute = new ReRouteBuilder() - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build()) .WithUpstreamHttpMethod(new List { "Get" }) .Build(); this.Given(x => x.GivenAReRoute(reRoute)) + .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) .Then(x => x.ThenTheLoadBalancerIsReturned()) @@ -46,10 +47,10 @@ namespace Ocelot.UnitTests.LoadBalancer var reRoute = new ReRouteBuilder() .WithLoadBalancer("RoundRobin") .WithUpstreamHttpMethod(new List { "Get" }) - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build()) .Build(); this.Given(x => x.GivenAReRoute(reRoute)) + .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) .Then(x => x.ThenTheLoadBalancerIsReturned()) @@ -62,10 +63,10 @@ namespace Ocelot.UnitTests.LoadBalancer var reRoute = new ReRouteBuilder() .WithLoadBalancer("LeastConnection") .WithUpstreamHttpMethod(new List { "Get" }) - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build()) .Build(); this.Given(x => x.GivenAReRoute(reRoute)) + .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) .Then(x => x.ThenTheLoadBalancerIsReturned()) @@ -78,27 +79,32 @@ namespace Ocelot.UnitTests.LoadBalancer var reRoute = new ReRouteBuilder() .WithLoadBalancer("RoundRobin") .WithUpstreamHttpMethod(new List { "Get" }) - .WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build()) .Build(); this.Given(x => x.GivenAReRoute(reRoute)) + .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) .Then(x => x.ThenTheServiceProviderIsCalledCorrectly()) .BDDfy(); } + private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig) + { + _serviceProviderConfig = serviceProviderConfig; + } + private void GivenTheServiceProviderFactoryReturns() { _serviceProviderFactory - .Setup(x => x.Get(It.IsAny())) + .Setup(x => x.Get(It.IsAny(), It.IsAny())) .Returns(_serviceProvider.Object); } private void ThenTheServiceProviderIsCalledCorrectly() { _serviceProviderFactory - .Verify(x => x.Get(It.IsAny()), Times.Once); + .Verify(x => x.Get(It.IsAny(), It.IsAny()), Times.Once); } private void GivenAReRoute(ReRoute reRoute) @@ -108,7 +114,7 @@ namespace Ocelot.UnitTests.LoadBalancer private void WhenIGetTheLoadBalancer() { - _result = _factory.Get(_reRoute).Result; + _result = _factory.Get(_reRoute, _serviceProviderConfig).Result; } private void ThenTheLoadBalancerIsReturned() diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs index ac24b490..ccfb32ff 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs @@ -1,5 +1,8 @@ using System; using System.Threading.Tasks; +using Moq; +using Ocelot.Configuration; +using Ocelot.Configuration.Builder; using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.Responses; using Ocelot.Values; @@ -11,35 +14,38 @@ namespace Ocelot.UnitTests.LoadBalancer { public class LoadBalancerHouseTests { + private ReRoute _reRoute; private ILoadBalancer _loadBalancer; private readonly LoadBalancerHouse _loadBalancerHouse; private Response _addResult; private Response _getResult; private string _key; + private Mock _factory; + private ServiceProviderConfiguration _serviceProviderConfig; public LoadBalancerHouseTests() { - _loadBalancerHouse = new LoadBalancerHouse(); + _factory = new Mock(); + _loadBalancerHouse = new LoadBalancerHouse(_factory.Object); } [Fact] - public void should_store_load_balancer() + public void should_store_load_balancer_on_first_request() { - var key = "test"; + var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); - this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer())) - .When(x => x.WhenIAddTheLoadBalancer()) + this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) .Then(x => x.ThenItIsAdded()) .BDDfy(); } [Fact] - public void should_get_load_balancer() + public void should_not_store_load_balancer_on_second_request() { - var key = "test"; + var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); - this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer())) - .When(x => x.WhenWeGetTheLoadBalancer(key)) + this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) + .When(x => x.WhenWeGetTheLoadBalancer(reRoute)) .Then(x => x.ThenItIsReturned()) .BDDfy(); } @@ -47,26 +53,50 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_store_load_balancers_by_key() { - var key = "test"; - var keyTwo = "testTwo"; + var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); + var reRouteTwo = new ReRouteBuilder().WithLoadBalancerKey("testtwo").Build(); - this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer())) - .And(x => x.GivenThereIsALoadBalancer(keyTwo, new FakeRoundRobinLoadBalancer())) - .When(x => x.WhenWeGetTheLoadBalancer(key)) + this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) + .And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer())) + .When(x => x.WhenWeGetTheLoadBalancer(reRoute)) .Then(x => x.ThenTheLoadBalancerIs()) - .When(x => x.WhenWeGetTheLoadBalancer(keyTwo)) + .When(x => x.WhenWeGetTheLoadBalancer(reRouteTwo)) .Then(x => x.ThenTheLoadBalancerIs()) .BDDfy(); } [Fact] - public void should_return_error_if_no_load_balancer_with_key() + public void should_return_error_if_exception() { - this.When(x => x.WhenWeGetTheLoadBalancer("test")) + var reRoute = new ReRouteBuilder().Build(); + + this.When(x => x.WhenWeGetTheLoadBalancer(reRoute)) .Then(x => x.ThenAnErrorIsReturned()) .BDDfy(); } + [Fact] + public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed() + { + var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); + + var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithLoadBalancerKey("test").Build(); + + this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) + .When(x => x.WhenWeGetTheLoadBalancer(reRoute)) + .Then(x => x.ThenTheLoadBalancerIs()) + .When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(reRouteTwo)) + .Then(x => x.ThenTheLoadBalancerIs()) + .BDDfy(); + } + + private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute) + { + _reRoute = reRoute; + _factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnectionLoadBalancer(null, null)); + _getResult = _loadBalancerHouse.Get(_reRoute, _serviceProviderConfig).Result; + } + private void ThenAnErrorIsReturned() { _getResult.IsError.ShouldBeTrue(); @@ -80,31 +110,30 @@ namespace Ocelot.UnitTests.LoadBalancer private void ThenItIsAdded() { - _addResult.IsError.ShouldBe(false); - _addResult.ShouldBeOfType(); - } - - private void WhenIAddTheLoadBalancer() - { - _addResult = _loadBalancerHouse.Add(_key, _loadBalancer); + _getResult.IsError.ShouldBe(false); + _getResult.ShouldBeOfType>(); + _getResult.Data.ShouldBe(_loadBalancer); + _factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once); } - private void GivenThereIsALoadBalancer(string key, ILoadBalancer loadBalancer) + private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer) { - _key = key; + _reRoute = reRoute; _loadBalancer = loadBalancer; - WhenIAddTheLoadBalancer(); + _factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(loadBalancer); + _getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result; } - private void WhenWeGetTheLoadBalancer(string key) + private void WhenWeGetTheLoadBalancer(ReRoute reRoute) { - _getResult = _loadBalancerHouse.Get(key); + _getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result; } private void ThenItIsReturned() { _getResult.Data.ShouldBe(_loadBalancer); + _factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once); } class FakeLoadBalancer : ILoadBalancer diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs index e483f31c..6ef4029b 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs @@ -5,6 +5,7 @@ namespace Ocelot.UnitTests.LoadBalancer using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Moq; + using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.DownstreamRouteFinder; using Ocelot.Errors; @@ -137,8 +138,8 @@ namespace Ocelot.UnitTests.LoadBalancer private void GivenTheLoadBalancerHouseReturns() { _loadBalancerHouse - .Setup(x => x.Get(It.IsAny())) - .Returns(new OkResponse(_loadBalancer.Object)); + .Setup(x => x.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(new OkResponse(_loadBalancer.Object)); } private void GivenTheLoadBalancerHouseReturnsAnError() @@ -149,8 +150,8 @@ namespace Ocelot.UnitTests.LoadBalancer }); _loadBalancerHouse - .Setup(x => x.Get(It.IsAny())) - .Returns(_getLoadBalancerHouseError); + .Setup(x => x.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(_getLoadBalancerHouseError); } private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline() diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs index afa86c1b..71ed1430 100644 --- a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs +++ b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs @@ -12,6 +12,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery private ServiceProviderConfiguration _serviceConfig; private IServiceDiscoveryProvider _result; private readonly ServiceDiscoveryProviderFactory _factory; + private ReRoute _reRoute; public ServiceProviderFactoryTests() { @@ -22,12 +23,11 @@ namespace Ocelot.UnitTests.ServiceDiscovery public void should_return_no_service_provider() { var serviceConfig = new ServiceProviderConfigurationBuilder() - .WithDownstreamHost("127.0.0.1") - .WithDownstreamPort(80) - .WithUseServiceDiscovery(false) .Build(); - this.Given(x => x.GivenTheReRoute(serviceConfig)) + var reRoute = new ReRouteBuilder().Build(); + + this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute)) .When(x => x.WhenIGetTheServiceProvider()) .Then(x => x.ThenTheServiceProviderIs()) .BDDfy(); @@ -36,26 +36,30 @@ namespace Ocelot.UnitTests.ServiceDiscovery [Fact] public void should_return_consul_service_provider() { - var serviceConfig = new ServiceProviderConfigurationBuilder() + var reRoute = new ReRouteBuilder() .WithServiceName("product") .WithUseServiceDiscovery(true) + .Build(); + + var serviceConfig = new ServiceProviderConfigurationBuilder() .WithServiceDiscoveryProvider("Consul") .Build(); - this.Given(x => x.GivenTheReRoute(serviceConfig)) + this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute)) .When(x => x.WhenIGetTheServiceProvider()) .Then(x => x.ThenTheServiceProviderIs()) .BDDfy(); } - private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig) + private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig, ReRoute reRoute) { _serviceConfig = serviceConfig; + _reRoute = reRoute; } private void WhenIGetTheServiceProvider() { - _result = _factory.Get(_serviceConfig); + _result = _factory.Get(_serviceConfig, _reRoute); } private void ThenTheServiceProviderIs()