diff --git a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs index b823e6ac..1a8877e7 100644 --- a/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ReRouteBuilder.cs @@ -149,7 +149,7 @@ namespace Ocelot.Configuration.Builder return this; } - public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey) + public ReRouteBuilder WithReRouteKey(string loadBalancerKey) { _loadBalancerKey = loadBalancerKey; return this; diff --git a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs index fe9f7f3c..3a9f7974 100644 --- a/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs +++ b/src/Ocelot/Configuration/Builder/ServiceProviderConfigurationBuilder.cs @@ -2,16 +2,9 @@ namespace Ocelot.Configuration.Builder { public class ServiceProviderConfigurationBuilder { - private string _serviceDiscoveryProvider; private string _serviceDiscoveryProviderHost; private int _serviceDiscoveryProviderPort; - public ServiceProviderConfigurationBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider) - { - _serviceDiscoveryProvider = serviceDiscoveryProvider; - return this; - } - public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost) { _serviceDiscoveryProviderHost = serviceDiscoveryProviderHost; @@ -26,7 +19,7 @@ namespace Ocelot.Configuration.Builder public ServiceProviderConfiguration Build() { - return new ServiceProviderConfiguration(_serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort); + return new ServiceProviderConfiguration(_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 cd6e54ff..bffb8392 100644 --- a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs @@ -26,8 +26,6 @@ namespace Ocelot.Configuration.Creator private readonly IOptions _options; private readonly IConfigurationValidator _configurationValidator; private readonly IOcelotLogger _logger; - private readonly IQoSProviderFactory _qoSProviderFactory; - private readonly IQosProviderHouse _qosProviderHouse; private readonly IClaimsToThingCreator _claimsToThingCreator; private readonly IAuthenticationOptionsCreator _authOptionsCreator; private readonly IUpstreamTemplatePatternCreator _upstreamTemplatePatternCreator; @@ -43,8 +41,6 @@ namespace Ocelot.Configuration.Creator IOptions options, IConfigurationValidator configurationValidator, IOcelotLoggerFactory loggerFactory, - IQoSProviderFactory qoSProviderFactory, - IQosProviderHouse qosProviderHouse, IClaimsToThingCreator claimsToThingCreator, IAuthenticationOptionsCreator authOptionsCreator, IUpstreamTemplatePatternCreator upstreamTemplatePatternCreator, @@ -62,8 +58,6 @@ namespace Ocelot.Configuration.Creator _requestIdKeyCreator = requestIdKeyCreator; _upstreamTemplatePatternCreator = upstreamTemplatePatternCreator; _authOptionsCreator = authOptionsCreator; - _qoSProviderFactory = qoSProviderFactory; - _qosProviderHouse = qosProviderHouse; _options = options; _configurationValidator = configurationValidator; _logger = loggerFactory.CreateLogger(); @@ -108,7 +102,7 @@ namespace Ocelot.Configuration.Creator foreach (var reRoute in fileConfiguration.ReRoutes) { - var ocelotReRoute = await SetUpReRoute(reRoute, fileConfiguration.GlobalConfiguration); + var ocelotReRoute = SetUpReRoute(reRoute, fileConfiguration.GlobalConfiguration); reRoutes.Add(ocelotReRoute); } @@ -117,7 +111,7 @@ namespace Ocelot.Configuration.Creator return new OcelotConfiguration(reRoutes, fileConfiguration.GlobalConfiguration.AdministrationPath, serviceProviderConfiguration); } - private async Task SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) + private ReRoute SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) { var fileReRouteOptions = _fileReRouteOptionsCreator.Create(fileReRoute); @@ -162,7 +156,7 @@ namespace Ocelot.Configuration.Creator .WithLoadBalancer(fileReRoute.LoadBalancer) .WithDownstreamHost(fileReRoute.DownstreamHost) .WithDownstreamPort(fileReRoute.DownstreamPort) - .WithLoadBalancerKey(reRouteKey) + .WithReRouteKey(reRouteKey) .WithIsQos(fileReRouteOptions.IsQos) .WithQosOptions(qosOptions) .WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting) @@ -172,7 +166,6 @@ namespace Ocelot.Configuration.Creator .WithUseServiceDiscovery(fileReRoute.UseServiceDiscovery) .Build(); - SetupQosProvider(reRoute); return reRoute; } @@ -182,11 +175,5 @@ namespace Ocelot.Configuration.Creator var loadBalancerKey = $"{fileReRoute.UpstreamPathTemplate}|{string.Join(",", fileReRoute.UpstreamHttpMethod)}"; return loadBalancerKey; } - - private void SetupQosProvider(ReRoute reRoute) - { - var loadBalancer = _qoSProviderFactory.Get(reRoute); - _qosProviderHouse.Add(reRoute.ReRouteKey, loadBalancer); - } } } \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs index a29e285c..4980ae69 100644 --- a/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/ServiceProviderConfigurationCreator.cs @@ -10,7 +10,6 @@ namespace Ocelot.Configuration.Creator var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0; return new ServiceProviderConfigurationBuilder() - .WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider) .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) .WithServiceDiscoveryProviderPort(serviceProviderPort) .Build(); diff --git a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs index 70a3c42f..37cac26f 100644 --- a/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs +++ b/src/Ocelot/Configuration/File/FileServiceDiscoveryProvider.cs @@ -2,8 +2,6 @@ namespace Ocelot.Configuration.File { public class FileServiceDiscoveryProvider { - - public string Provider {get;set;} public string Host {get;set;} public int Port { get; set; } } diff --git a/src/Ocelot/Configuration/Repository/ConsulOcelotConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/ConsulOcelotConfigurationRepository.cs index 25c5b00a..c7de98d2 100644 --- a/src/Ocelot/Configuration/Repository/ConsulOcelotConfigurationRepository.cs +++ b/src/Ocelot/Configuration/Repository/ConsulOcelotConfigurationRepository.cs @@ -11,19 +11,19 @@ namespace Ocelot.Configuration.Repository public class ConsulOcelotConfigurationRepository : IOcelotConfigurationRepository { private readonly ConsulClient _consul; - private ConsulRegistryConfiguration _configuration; private string _ocelotConfiguration = "OcelotConfiguration"; - private Cache.IOcelotCache _cache; + private readonly Cache.IOcelotCache _cache; - public ConsulOcelotConfigurationRepository(ConsulRegistryConfiguration consulRegistryConfiguration, Cache.IOcelotCache cache) + + public ConsulOcelotConfigurationRepository(Cache.IOcelotCache cache, ServiceProviderConfiguration serviceProviderConfig) { - var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName; - var consulPort = consulRegistryConfiguration?.Port ?? 8500; - _configuration = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.ServiceName); + var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.ServiceProviderHost) ? "localhost" : serviceProviderConfig?.ServiceProviderHost; + var consulPort = serviceProviderConfig?.ServiceProviderPort ?? 8500; + var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration); _cache = cache; - _consul = new ConsulClient(config => + _consul = new ConsulClient(c => { - config.Address = new Uri($"http://{_configuration.HostName}:{_configuration.Port}"); + c.Address = new Uri($"http://{configuration.HostName}:{configuration.Port}"); }); } diff --git a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs index 46351044..d5ddea6a 100644 --- a/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs +++ b/src/Ocelot/Configuration/ServiceProviderConfiguraion.cs @@ -2,14 +2,12 @@ { public class ServiceProviderConfiguration { - public ServiceProviderConfiguration(string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort) + public ServiceProviderConfiguration(string serviceProviderHost, int serviceProviderPort) { - ServiceDiscoveryProvider = serviceDiscoveryProvider; ServiceProviderHost = serviceProviderHost; ServiceProviderPort = serviceProviderPort; } - 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 33f6dabb..32e29c04 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -45,20 +45,39 @@ using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Ocelot.Configuration; +using Ocelot.Configuration.Builder; using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider; -using Ocelot.LoadBalancer; namespace Ocelot.DependencyInjection { public static class ServiceCollectionExtensions { - public static IServiceCollection AddOcelotStoreConfigurationInConsul(this IServiceCollection services, ConsulRegistryConfiguration consulConfig) + public static IServiceCollection AddStoreOcelotConfigurationInConsul(this IServiceCollection services, IConfigurationRoot configurationRoot) { - services.AddSingleton(consulConfig); + var serviceDiscoveryPort = configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0); + var serviceDiscoveryHost = configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty); + + var config = new ServiceProviderConfigurationBuilder() + .WithServiceDiscoveryProviderPort(serviceDiscoveryPort) + .WithServiceDiscoveryProviderHost(serviceDiscoveryHost) + .Build(); + + services.AddSingleton(config); services.AddSingleton(); return services; } + public static IServiceCollection AddOcelot(this IServiceCollection services, + IConfigurationRoot configurationRoot) + { + Action defaultCachingSettings = x => + { + x.WithDictionaryHandle(); + }; + + return services.AddOcelot(configurationRoot, defaultCachingSettings); + } + public static IServiceCollection AddOcelot(this IServiceCollection services, IConfigurationRoot configurationRoot, Action settings) { var cacheManagerOutputCache = CacheFactory.Build("OcelotOutputCache", settings); diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/LeastConnectionLoadBalancer.cs b/src/Ocelot/LoadBalancer/LoadBalancers/LeastConnection.cs similarity index 96% rename from src/Ocelot/LoadBalancer/LoadBalancers/LeastConnectionLoadBalancer.cs rename to src/Ocelot/LoadBalancer/LoadBalancers/LeastConnection.cs index cd56ef91..0e136b4a 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LeastConnectionLoadBalancer.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LeastConnection.cs @@ -8,14 +8,14 @@ using Ocelot.Values; namespace Ocelot.LoadBalancer.LoadBalancers { - public class LeastConnectionLoadBalancer : ILoadBalancer + public class LeastConnection : ILoadBalancer { private readonly Func>> _services; private readonly List _leases; private readonly string _serviceName; private static readonly object _syncLock = new object(); - public LeastConnectionLoadBalancer(Func>> services, string serviceName) + public LeastConnection(Func>> services, string serviceName) { _services = services; _serviceName = serviceName; diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs index 596a1c22..b3d68672 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs @@ -19,9 +19,9 @@ namespace Ocelot.LoadBalancer.LoadBalancers switch (reRoute.LoadBalancer) { case "RoundRobin": - return new RoundRobinLoadBalancer(async () => await serviceProvider.Get()); + return new RoundRobin(async () => await serviceProvider.Get()); case "LeastConnection": - return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceName); + return new LeastConnection(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 d4a54bd7..9e0ef296 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerHouse.cs @@ -22,16 +22,11 @@ namespace Ocelot.LoadBalancer.LoadBalancers { try { - ILoadBalancer loadBalancer; - - if(_loadBalancers.TryGetValue(reRoute.ReRouteKey, out loadBalancer)) + if(_loadBalancers.TryGetValue(reRoute.ReRouteKey, out var 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))) + if(reRoute.LoadBalancer != loadBalancer.GetType().Name) { loadBalancer = await _factory.Get(reRoute, config); AddLoadBalancer(reRoute.ReRouteKey, loadBalancer); @@ -55,18 +50,7 @@ namespace Ocelot.LoadBalancer.LoadBalancers private void AddLoadBalancer(string key, ILoadBalancer loadBalancer) { - _loadBalancers.AddOrUpdate(key, loadBalancer, (x, y) => { - return loadBalancer; - }); - - // if (!_loadBalancers.ContainsKey(key)) - // { - // _loadBalancers.TryAdd(key, loadBalancer); - // } - - // ILoadBalancer old; - // _loadBalancers.Remove(key, out old); - // _loadBalancers.TryAdd(key, loadBalancer); + _loadBalancers.AddOrUpdate(key, loadBalancer, (x, y) => loadBalancer); } } } diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobinLoadBalancer.cs b/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs similarity index 85% rename from src/Ocelot/LoadBalancer/LoadBalancers/RoundRobinLoadBalancer.cs rename to src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs index 4bc78915..817a1b8f 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobinLoadBalancer.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/RoundRobin.cs @@ -6,13 +6,13 @@ using System; namespace Ocelot.LoadBalancer.LoadBalancers { - public class RoundRobinLoadBalancer : ILoadBalancer + public class RoundRobin : ILoadBalancer { private readonly Func>> _services; private int _last; - public RoundRobinLoadBalancer(Func>> services) + public RoundRobin(Func>> services) { _services = services; } diff --git a/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs index 8e05f2ea..d04e76e2 100644 --- a/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs +++ b/src/Ocelot/Request/Middleware/HttpRequestBuilderMiddleware.cs @@ -32,7 +32,7 @@ namespace Ocelot.Request.Middleware { _logger.LogDebug("started calling request builder middleware"); - var qosProvider = _qosProviderHouse.Get(DownstreamRoute.ReRoute.ReRouteKey); + var qosProvider = _qosProviderHouse.Get(DownstreamRoute.ReRoute); if (qosProvider.IsError) { diff --git a/src/Ocelot/Requester/QoS/CircuitBreaker.cs b/src/Ocelot/Requester/QoS/CircuitBreaker.cs new file mode 100644 index 00000000..4b1a0d79 --- /dev/null +++ b/src/Ocelot/Requester/QoS/CircuitBreaker.cs @@ -0,0 +1,17 @@ +using Polly.CircuitBreaker; +using Polly.Timeout; + +namespace Ocelot.Requester.QoS +{ + public class CircuitBreaker + { + public CircuitBreaker(CircuitBreakerPolicy circuitBreakerPolicy, TimeoutPolicy timeoutPolicy) + { + CircuitBreakerPolicy = circuitBreakerPolicy; + TimeoutPolicy = timeoutPolicy; + } + + public CircuitBreakerPolicy CircuitBreakerPolicy { get; private set; } + public TimeoutPolicy TimeoutPolicy { get; private set; } + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/IQoSProvider.cs b/src/Ocelot/Requester/QoS/IQoSProvider.cs new file mode 100644 index 00000000..75fc48e3 --- /dev/null +++ b/src/Ocelot/Requester/QoS/IQoSProvider.cs @@ -0,0 +1,7 @@ +namespace Ocelot.Requester.QoS +{ + public interface IQoSProvider + { + CircuitBreaker CircuitBreaker { get; } + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/IQoSProviderFactory.cs b/src/Ocelot/Requester/QoS/IQoSProviderFactory.cs index feabfc09..ae23c397 100644 --- a/src/Ocelot/Requester/QoS/IQoSProviderFactory.cs +++ b/src/Ocelot/Requester/QoS/IQoSProviderFactory.cs @@ -1,13 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using Ocelot.Configuration; +using Ocelot.Configuration; using Ocelot.LoadBalancer.LoadBalancers; -using Ocelot.Logging; -using Ocelot.Responses; -using Polly; -using Polly.CircuitBreaker; -using Polly.Timeout; namespace Ocelot.Requester.QoS { @@ -15,131 +7,4 @@ namespace Ocelot.Requester.QoS { IQoSProvider Get(ReRoute reRoute); } - - public class QoSProviderFactory : IQoSProviderFactory - { - private readonly IOcelotLoggerFactory _loggerFactory; - - public QoSProviderFactory(IOcelotLoggerFactory loggerFactory) - { - _loggerFactory = loggerFactory; - } - - public IQoSProvider Get(ReRoute reRoute) - { - if (reRoute.IsQos) - { - return new PollyQoSProvider(reRoute, _loggerFactory); - } - - return new NoQoSProvider(); - } - } - - public interface IQoSProvider - { - CircuitBreaker CircuitBreaker { get; } - } - - public class NoQoSProvider : IQoSProvider - { - public CircuitBreaker CircuitBreaker { get; } - } - - public class PollyQoSProvider : IQoSProvider - { - private readonly CircuitBreakerPolicy _circuitBreakerPolicy; - private readonly TimeoutPolicy _timeoutPolicy; - private readonly IOcelotLogger _logger; - private readonly CircuitBreaker _circuitBreaker; - - public PollyQoSProvider(ReRoute reRoute, IOcelotLoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - - _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy); - - _circuitBreakerPolicy = Policy - .Handle() - .Or() - .Or() - .CircuitBreakerAsync( - exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking, - durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak), - onBreak: (ex, breakDelay) => - { - _logger.LogError( - ".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex); - }, - onReset: () => - { - _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."); - }, - onHalfOpen: () => - { - _logger.LogDebug(".Breaker logging: Half-open; next call is a trial."); - } - ); - - _circuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy); - } - - public CircuitBreaker CircuitBreaker => _circuitBreaker; - } - - public class CircuitBreaker - { - public CircuitBreaker(CircuitBreakerPolicy circuitBreakerPolicy, TimeoutPolicy timeoutPolicy) - { - CircuitBreakerPolicy = circuitBreakerPolicy; - TimeoutPolicy = timeoutPolicy; - } - - public CircuitBreakerPolicy CircuitBreakerPolicy { get; private set; } - public TimeoutPolicy TimeoutPolicy { get; private set; } - } - - - public interface IQosProviderHouse - { - Response Get(string key); - Response Add(string key, IQoSProvider loadBalancer); - } - - public class QosProviderHouse : IQosProviderHouse - { - private readonly Dictionary _qoSProviders; - - public QosProviderHouse() - { - _qoSProviders = new Dictionary(); - } - - public Response Get(string key) - { - IQoSProvider qoSProvider; - - if (_qoSProviders.TryGetValue(key, out qoSProvider)) - { - return new OkResponse(_qoSProviders[key]); - } - - return new ErrorResponse(new List() - { - new UnableToFindQoSProviderError($"unabe to find qos provider for {key}") - }); - } - - public Response Add(string key, IQoSProvider loadBalancer) - { - if (!_qoSProviders.ContainsKey(key)) - { - _qoSProviders.Add(key, loadBalancer); - } - - _qoSProviders.Remove(key); - _qoSProviders.Add(key, loadBalancer); - return new OkResponse(); - } - } } diff --git a/src/Ocelot/Requester/QoS/IQosProviderHouse.cs b/src/Ocelot/Requester/QoS/IQosProviderHouse.cs new file mode 100644 index 00000000..1ec0cf73 --- /dev/null +++ b/src/Ocelot/Requester/QoS/IQosProviderHouse.cs @@ -0,0 +1,10 @@ +using Ocelot.Configuration; +using Ocelot.Responses; + +namespace Ocelot.Requester.QoS +{ + public interface IQosProviderHouse + { + Response Get(ReRoute reRoute); + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/NoQoSProvider.cs b/src/Ocelot/Requester/QoS/NoQoSProvider.cs new file mode 100644 index 00000000..51d879de --- /dev/null +++ b/src/Ocelot/Requester/QoS/NoQoSProvider.cs @@ -0,0 +1,7 @@ +namespace Ocelot.Requester.QoS +{ + public class NoQoSProvider : IQoSProvider + { + public CircuitBreaker CircuitBreaker { get; } + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/PollyQoSProvider.cs b/src/Ocelot/Requester/QoS/PollyQoSProvider.cs new file mode 100644 index 00000000..69f7e608 --- /dev/null +++ b/src/Ocelot/Requester/QoS/PollyQoSProvider.cs @@ -0,0 +1,51 @@ +using System; +using System.Net.Http; +using Ocelot.Configuration; +using Ocelot.Logging; +using Polly; +using Polly.CircuitBreaker; +using Polly.Timeout; + +namespace Ocelot.Requester.QoS +{ + public class PollyQoSProvider : IQoSProvider + { + private readonly CircuitBreakerPolicy _circuitBreakerPolicy; + private readonly TimeoutPolicy _timeoutPolicy; + private readonly IOcelotLogger _logger; + private readonly CircuitBreaker _circuitBreaker; + + public PollyQoSProvider(ReRoute reRoute, IOcelotLoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + + _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy); + + _circuitBreakerPolicy = Policy + .Handle() + .Or() + .Or() + .CircuitBreakerAsync( + exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking, + durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak), + onBreak: (ex, breakDelay) => + { + _logger.LogError( + ".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex); + }, + onReset: () => + { + _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again."); + }, + onHalfOpen: () => + { + _logger.LogDebug(".Breaker logging: Half-open; next call is a trial."); + } + ); + + _circuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy); + } + + public CircuitBreaker CircuitBreaker => _circuitBreaker; + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/QoSProviderFactory.cs b/src/Ocelot/Requester/QoS/QoSProviderFactory.cs new file mode 100644 index 00000000..59ce123e --- /dev/null +++ b/src/Ocelot/Requester/QoS/QoSProviderFactory.cs @@ -0,0 +1,25 @@ +using Ocelot.Configuration; +using Ocelot.Logging; + +namespace Ocelot.Requester.QoS +{ + public class QoSProviderFactory : IQoSProviderFactory + { + private readonly IOcelotLoggerFactory _loggerFactory; + + public QoSProviderFactory(IOcelotLoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + } + + public IQoSProvider Get(ReRoute reRoute) + { + if (reRoute.IsQos) + { + return new PollyQoSProvider(reRoute, _loggerFactory); + } + + return new NoQoSProvider(); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/Requester/QoS/QosProviderHouse.cs b/src/Ocelot/Requester/QoS/QosProviderHouse.cs new file mode 100644 index 00000000..780f8181 --- /dev/null +++ b/src/Ocelot/Requester/QoS/QosProviderHouse.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using Ocelot.Configuration; +using Ocelot.Responses; + +namespace Ocelot.Requester.QoS +{ + public class QosProviderHouse : IQosProviderHouse + { + private readonly ConcurrentDictionary _qoSProviders; + private readonly IQoSProviderFactory _qoSProviderFactory; + + public QosProviderHouse(IQoSProviderFactory qoSProviderFactory) + { + _qoSProviderFactory = qoSProviderFactory; + _qoSProviders = new ConcurrentDictionary(); + } + + public Response Get(ReRoute reRoute) + { + try + { + if (_qoSProviders.TryGetValue(reRoute.ReRouteKey, out var qosProvider)) + { + if (reRoute.IsQos && qosProvider.CircuitBreaker == null) + { + qosProvider = _qoSProviderFactory.Get(reRoute); + Add(reRoute.ReRouteKey, qosProvider); + } + + return new OkResponse(_qoSProviders[reRoute.ReRouteKey]); + } + + qosProvider = _qoSProviderFactory.Get(reRoute); + Add(reRoute.ReRouteKey, qosProvider); + return new OkResponse(qosProvider); + } + catch (Exception ex) + { + return new ErrorResponse(new List() + { + new UnableToFindQoSProviderError($"unabe to find qos provider for {reRoute.ReRouteKey}, exception was {ex}") + }); + } + } + + private void Add(string key, IQoSProvider qosProvider) + { + _qoSProviders.AddOrUpdate(key, qosProvider, (x, y) => qosProvider); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs b/src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs index 8d496a85..e06c22bd 100644 --- a/src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs +++ b/src/Ocelot/ServiceDiscovery/ConsulRegistryConfiguration.cs @@ -2,14 +2,14 @@ namespace Ocelot.ServiceDiscovery { public class ConsulRegistryConfiguration { - public ConsulRegistryConfiguration(string hostName, int port, string serviceName) + public ConsulRegistryConfiguration(string hostName, int port, string keyOfServiceInConsul) { HostName = hostName; Port = port; - ServiceName = serviceName; + KeyOfServiceInConsul = keyOfServiceInConsul; } - public string ServiceName { get; private set; } + public string KeyOfServiceInConsul { get; private set; } public string HostName { get; private set; } public int Port { get; private set; } } diff --git a/src/Ocelot/ServiceDiscovery/ConsulServiceDiscoveryProvider.cs b/src/Ocelot/ServiceDiscovery/ConsulServiceDiscoveryProvider.cs index c74c90f0..5dd906f9 100644 --- a/src/Ocelot/ServiceDiscovery/ConsulServiceDiscoveryProvider.cs +++ b/src/Ocelot/ServiceDiscovery/ConsulServiceDiscoveryProvider.cs @@ -10,7 +10,7 @@ namespace Ocelot.ServiceDiscovery { public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider { - private readonly ConsulRegistryConfiguration _configuration; + private readonly ConsulRegistryConfiguration _consulConfig; private readonly ConsulClient _consul; private const string VersionPrefix = "version-"; @@ -18,17 +18,17 @@ namespace Ocelot.ServiceDiscovery { var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName; var consulPort = consulRegistryConfiguration?.Port ?? 8500; - _configuration = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.ServiceName); + _consulConfig = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.KeyOfServiceInConsul); _consul = new ConsulClient(config => { - config.Address = new Uri($"http://{_configuration.HostName}:{_configuration.Port}"); + config.Address = new Uri($"http://{_consulConfig.HostName}:{_consulConfig.Port}"); }); } public async Task> Get() { - var queryResult = await _consul.Health.Service(_configuration.ServiceName, string.Empty, true); + var queryResult = await _consul.Health.Service(_consulConfig.KeyOfServiceInConsul, string.Empty, true); var services = queryResult.Response.Select(BuildService); diff --git a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs index 5dc4982a..cd724292 100644 --- a/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/ServiceDiscoveryProviderFactory.cs @@ -10,7 +10,7 @@ namespace Ocelot.ServiceDiscovery { if (reRoute.UseServiceDiscovery) { - return GetServiceDiscoveryProvider(reRoute.ServiceName, serviceConfig.ServiceDiscoveryProvider, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort); + return GetServiceDiscoveryProvider(reRoute.ServiceName, serviceConfig.ServiceProviderHost, serviceConfig.ServiceProviderPort); } var services = new List() @@ -25,9 +25,9 @@ namespace Ocelot.ServiceDiscovery return new ConfigurationServiceProvider(services); } - private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string serviceName, string serviceProviderName, string providerHostName, int providerPort) + private IServiceDiscoveryProvider GetServiceDiscoveryProvider(string keyOfServiceInConsul, string providerHostName, int providerPort) { - var consulRegistryConfiguration = new ConsulRegistryConfiguration(providerHostName, providerPort, serviceName); + var consulRegistryConfiguration = new ConsulRegistryConfiguration(providerHostName, providerPort, keyOfServiceInConsul); return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration); } } diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index 90db18e3..aca07a3c 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -3,7 +3,6 @@ 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; @@ -11,7 +10,6 @@ using Newtonsoft.Json; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.Configuration.File; -using Ocelot.ServiceDiscovery; using TestStack.BDDfy; using Xunit; @@ -50,7 +48,6 @@ namespace Ocelot.AcceptanceTests { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() { - Provider = "Consul", Host = "localhost", Port = 9500 } @@ -59,12 +56,10 @@ namespace Ocelot.AcceptanceTests var fakeConsulServiceDiscoveryUrl = "http://localhost:9500"; - 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 => _steps.GivenThereIsAConfiguration(configuration)) - .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig)) + .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) @@ -73,31 +68,25 @@ namespace Ocelot.AcceptanceTests [Fact] public void should_fix_issue_142() - { + { + var consulPort = 8500; var configuration = new FileConfiguration { - ReRoutes = new List - { - }, GlobalConfiguration = new FileGlobalConfiguration() { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() { - Provider = "Consul", Host = "localhost", - Port = 9500 + Port = consulPort } } }; - var fakeConsulServiceDiscoveryUrl = "http://localhost:9500"; - - var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot"); + var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}"; var serviceProviderConfig = new ServiceProviderConfigurationBuilder() - .WithServiceDiscoveryProvider("Consul") .WithServiceDiscoveryProviderHost("localhost") - .WithServiceDiscoveryProviderPort(8500) + .WithServiceDiscoveryProviderPort(consulPort) .Build(); var reRoute = new ReRouteBuilder() @@ -108,10 +97,8 @@ namespace Ocelot.AcceptanceTests .WithDownstreamPort(51779) .WithUpstreamPathTemplate("/cs/status") .WithUpstreamHttpMethod(new List {"Get"}) - .WithLoadBalancer("LeastConnection") - .WithLoadBalancerKey("/cs/status|Get") - .WithServiceName("") - .WithUseServiceDiscovery(true) + .WithReRouteKey("/cs/status|Get") + .WithHttpHandlerOptions(new HttpHandlerOptions(true, false)) .Build(); var reRoutes = new List { reRoute }; @@ -122,7 +109,7 @@ namespace Ocelot.AcceptanceTests .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)) + .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig()) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/cs/status")) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) diff --git a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs index a856656e..2c7b6b56 100644 --- a/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs +++ b/test/Ocelot.AcceptanceTests/ServiceDiscoveryTests.cs @@ -33,10 +33,11 @@ namespace Ocelot.AcceptanceTests [Fact] public void should_use_service_discovery_and_load_balance_request() { + var consulPort = 8501; var serviceName = "product"; var downstreamServiceOneUrl = "http://localhost:50879"; var downstreamServiceTwoUrl = "http://localhost:50880"; - var fakeConsulServiceDiscoveryUrl = "http://localhost:8500"; + var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}"; var serviceEntryOne = new ServiceEntry() { Service = new AgentService() @@ -79,9 +80,8 @@ namespace Ocelot.AcceptanceTests { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider() { - Provider = "Consul", Host = "localhost", - Port = 8500 + Port = consulPort } } }; diff --git a/test/Ocelot.AcceptanceTests/Startup.cs b/test/Ocelot.AcceptanceTests/Startup.cs index 3a53bfaa..1dacaec2 100644 --- a/test/Ocelot.AcceptanceTests/Startup.cs +++ b/test/Ocelot.AcceptanceTests/Startup.cs @@ -44,4 +44,39 @@ namespace Ocelot.AcceptanceTests app.UseOcelot().Wait(); } } + + public class ConsulStartup + { + public ConsulStartup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) + .AddJsonFile("configuration.json") + .AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + public void ConfigureServices(IServiceCollection services) + { + Action settings = (x) => + { + x.WithDictionaryHandle(); + }; + + services.AddOcelot(Configuration, settings); + services.AddStoreOcelotConfigurationInConsul(Configuration); + } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + + app.UseOcelot().Wait(); + } + } } diff --git a/test/Ocelot.AcceptanceTests/Steps.cs b/test/Ocelot.AcceptanceTests/Steps.cs index 80a3e68e..04f8343e 100644 --- a/test/Ocelot.AcceptanceTests/Steps.cs +++ b/test/Ocelot.AcceptanceTests/Steps.cs @@ -107,18 +107,17 @@ namespace Ocelot.AcceptanceTests _ocelotClient = _ocelotServer.CreateClient(); } - public void GivenOcelotIsRunningUsingConsulToStoreConfig(ConsulRegistryConfiguration consulConfig) + public void GivenOcelotIsRunningUsingConsulToStoreConfig(/*ConsulRegistryConfiguration consulConfig*/) { _webHostBuilder = new WebHostBuilder(); _webHostBuilder.ConfigureServices(s => { s.AddSingleton(_webHostBuilder); - s.AddOcelotStoreConfigurationInConsul(consulConfig); }); _ocelotServer = new TestServer(_webHostBuilder - .UseStartup()); + .UseStartup()); _ocelotClient = _ocelotServer.CreateClient(); } @@ -131,7 +130,6 @@ namespace Ocelot.AcceptanceTests response.GlobalConfiguration.RequestIdKey.ShouldBe(expected.GlobalConfiguration.RequestIdKey); response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Host); response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Port); - response.GlobalConfiguration.ServiceDiscoveryProvider.Provider.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Provider); for(var i = 0; i < response.ReRoutes.Count; i++) { diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index 7cc88ed8..240b7c25 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -107,7 +107,6 @@ namespace Ocelot.IntegrationTests ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { Host = "127.0.0.1", - Provider = "test" } }, @@ -332,7 +331,6 @@ namespace Ocelot.IntegrationTests response.GlobalConfiguration.RequestIdKey.ShouldBe(expected.GlobalConfiguration.RequestIdKey); response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Host); response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Port); - response.GlobalConfiguration.ServiceDiscoveryProvider.Provider.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Provider); for (var i = 0; i < response.ReRoutes.Count; i++) { diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index b9264cee..09489523 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using Ocelot.Cache; @@ -8,9 +7,7 @@ using Ocelot.Configuration.Builder; using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; using Ocelot.Configuration.Validator; -using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.Logging; -using Ocelot.Requester.QoS; using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; @@ -18,8 +15,6 @@ using Xunit; namespace Ocelot.UnitTests.Configuration { - using System.Collections; - using Ocelot.LoadBalancer; using Ocelot.UnitTests.TestData; public class FileConfigurationCreatorTests @@ -30,10 +25,6 @@ namespace Ocelot.UnitTests.Configuration private FileConfiguration _fileConfiguration; private readonly Mock _logger; private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator; - private readonly Mock _loadBalancer; - private readonly Mock _qosProviderFactory; - private readonly Mock _qosProviderHouse; - private readonly Mock _qosProvider; private Mock _claimsToThingCreator; private Mock _authOptionsCreator; private Mock _upstreamTemplatePatternCreator; @@ -47,13 +38,9 @@ namespace Ocelot.UnitTests.Configuration public FileConfigurationCreatorTests() { - _qosProviderFactory = new Mock(); - _qosProviderHouse = new Mock(); - _qosProvider = new Mock(); _logger = new Mock(); _validator = new Mock(); _fileConfig = new Mock>(); - _loadBalancer = new Mock(); _claimsToThingCreator = new Mock(); _authOptionsCreator = new Mock(); _upstreamTemplatePatternCreator = new Mock(); @@ -67,7 +54,7 @@ namespace Ocelot.UnitTests.Configuration _ocelotConfigurationCreator = new FileOcelotConfigurationCreator( _fileConfig.Object, _validator.Object, _logger.Object, - _qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object, + _claimsToThingCreator.Object, _authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object, _serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object, _rateLimitOptions.Object, _regionCreator.Object, _httpHandlerOptionsCreator.Object); @@ -86,7 +73,6 @@ namespace Ocelot.UnitTests.Configuration { Host = "localhost", Port = 8500, - Provider = "consul" } } })) @@ -201,12 +187,9 @@ namespace Ocelot.UnitTests.Configuration })) .And(x => x.GivenTheConfigIsValid()) .And(x => x.GivenTheFollowingOptionsAreReturned(serviceOptions)) - .And(x => x.GivenTheQosProviderFactoryReturns()) .And(x => x.GivenTheQosOptionsCreatorReturns(expected)) .When(x => x.WhenICreateTheConfig()) .Then(x => x.ThenTheQosOptionsAre(expected)) - .And(x => x.TheQosProviderFactoryIsCalledCorrectly()) - .And(x => x.ThenTheQosProviderHouseIsCalledCorrectly()) .BDDfy(); } @@ -301,7 +284,6 @@ namespace Ocelot.UnitTests.Configuration { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { - Provider = "consul", Host = "127.0.0.1" } } @@ -603,25 +585,6 @@ namespace Ocelot.UnitTests.Configuration } } - private void GivenTheQosProviderFactoryReturns() - { - _qosProviderFactory - .Setup(x => x.Get(It.IsAny())) - .Returns(_qosProvider.Object); - } - - private void TheQosProviderFactoryIsCalledCorrectly() - { - _qosProviderFactory - .Verify(x => x.Get(It.IsAny()), Times.Once); - } - - private void ThenTheQosProviderHouseIsCalledCorrectly() - { - _qosProviderHouse - .Verify(x => x.Add(It.IsAny(), _qosProvider.Object), Times.Once); - } - private void GivenTheClaimsToThingCreatorReturns(List claimsToThing) { _claimsToThingCreator diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs index dfa8f67a..33e95910 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs @@ -43,7 +43,6 @@ namespace Ocelot.UnitTests.Configuration AdministrationPath = "testy", ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { - Provider = "consul", Port = 198, Host = "blah" } @@ -78,7 +77,6 @@ namespace Ocelot.UnitTests.Configuration AdministrationPath = "asdas", ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { - Provider = "consul", Port = 198, Host = "blah" } @@ -111,7 +109,6 @@ namespace Ocelot.UnitTests.Configuration _result.GlobalConfiguration.RequestIdKey.ShouldBe(expected.GlobalConfiguration.RequestIdKey); _result.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Host); _result.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Port); - _result.GlobalConfiguration.ServiceDiscoveryProvider.Provider.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Provider); for(var i = 0; i < _result.ReRoutes.Count; i++) { @@ -147,7 +144,6 @@ namespace Ocelot.UnitTests.Configuration _result.GlobalConfiguration.RequestIdKey.ShouldBe(expected.GlobalConfiguration.RequestIdKey); _result.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Host); _result.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Port); - _result.GlobalConfiguration.ServiceDiscoveryProvider.Provider.ShouldBe(expected.GlobalConfiguration.ServiceDiscoveryProvider.Provider); for(var i = 0; i < _result.ReRoutes.Count; i++) { diff --git a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs index 8c33b4e5..2d9fe3a2 100644 --- a/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/ServiceProviderCreatorTests.cs @@ -29,14 +29,12 @@ namespace Ocelot.UnitTests.Configuration { ServiceDiscoveryProvider = new FileServiceDiscoveryProvider { - Provider = "consul", Host = "127.0.0.1", Port = 1234 } }; var expected = new ServiceProviderConfigurationBuilder() - .WithServiceDiscoveryProvider("consul") .WithServiceDiscoveryProviderHost("127.0.0.1") .WithServiceDiscoveryProviderPort(1234) .Build(); @@ -65,7 +63,6 @@ namespace Ocelot.UnitTests.Configuration private void ThenTheConfigIs(ServiceProviderConfiguration expected) { - _result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider); _result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost); _result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort); } diff --git a/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs index 07002ce3..936a57e8 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LeastConnectionTests.cs @@ -14,7 +14,7 @@ namespace Ocelot.UnitTests.LoadBalancer { private HostAndPort _hostAndPort; private Response _result; - private LeastConnectionLoadBalancer _leastConnection; + private LeastConnection _leastConnection; private List _services; private Random _random; @@ -35,7 +35,7 @@ namespace Ocelot.UnitTests.LoadBalancer }; _services = availableServices; - _leastConnection = new LeastConnectionLoadBalancer(() => Task.FromResult(_services), serviceName); + _leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName); var tasks = new Task[100]; @@ -86,7 +86,7 @@ namespace Ocelot.UnitTests.LoadBalancer }; _services = availableServices; - _leastConnection = new LeastConnectionLoadBalancer(() => Task.FromResult(_services), serviceName); + _leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName); var response = _leastConnection.Lease().Result; @@ -113,7 +113,7 @@ namespace Ocelot.UnitTests.LoadBalancer }; _services = availableServices; - _leastConnection = new LeastConnectionLoadBalancer(() => Task.FromResult(_services), serviceName); + _leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName); var response = _leastConnection.Lease().Result; @@ -144,7 +144,7 @@ namespace Ocelot.UnitTests.LoadBalancer }; _services = availableServices; - _leastConnection = new LeastConnectionLoadBalancer(() => Task.FromResult(_services), serviceName); + _leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName); var response = _leastConnection.Lease().Result; @@ -211,7 +211,7 @@ namespace Ocelot.UnitTests.LoadBalancer private void GivenTheLoadBalancerStarts(List services, string serviceName) { _services = services; - _leastConnection = new LeastConnectionLoadBalancer(() => Task.FromResult(_services), serviceName); + _leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName); } private void WhenTheLoadBalancerStarts(List services, string serviceName) diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs index 9fde2f78..d630393b 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs @@ -53,7 +53,7 @@ namespace Ocelot.UnitTests.LoadBalancer .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) - .Then(x => x.ThenTheLoadBalancerIsReturned()) + .Then(x => x.ThenTheLoadBalancerIsReturned()) .BDDfy(); } @@ -69,7 +69,7 @@ namespace Ocelot.UnitTests.LoadBalancer .And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build())) .And(x => x.GivenTheServiceProviderFactoryReturns()) .When(x => x.WhenIGetTheLoadBalancer()) - .Then(x => x.ThenTheLoadBalancerIsReturned()) + .Then(x => x.ThenTheLoadBalancerIsReturned()) .BDDfy(); } diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs index ccfb32ff..a5211859 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerHouseTests.cs @@ -32,7 +32,7 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_store_load_balancer_on_first_request() { - var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) .Then(x => x.ThenItIsAdded()) @@ -42,7 +42,7 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_not_store_load_balancer_on_second_request() { - var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); + var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build(); this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) .When(x => x.WhenWeGetTheLoadBalancer(reRoute)) @@ -53,8 +53,8 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_store_load_balancers_by_key() { - var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); - var reRouteTwo = new ReRouteBuilder().WithLoadBalancerKey("testtwo").Build(); + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); + var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testtwo").Build(); this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer())) .And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer())) @@ -78,22 +78,22 @@ namespace Ocelot.UnitTests.LoadBalancer [Fact] public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed() { - var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build(); + var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build(); - var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithLoadBalancerKey("test").Build(); + var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithReRouteKey("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()) + .Then(x => x.ThenTheLoadBalancerIs()) .BDDfy(); } private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute) { _reRoute = reRoute; - _factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnectionLoadBalancer(null, null)); + _factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnection(null, null)); _getResult = _loadBalancerHouse.Get(_reRoute, _serviceProviderConfig).Result; } diff --git a/test/Ocelot.UnitTests/LoadBalancer/RoundRobinTests.cs b/test/Ocelot.UnitTests/LoadBalancer/RoundRobinTests.cs index 0820b8be..458df669 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/RoundRobinTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/RoundRobinTests.cs @@ -12,7 +12,7 @@ namespace Ocelot.UnitTests.LoadBalancer { public class RoundRobinTests { - private readonly RoundRobinLoadBalancer _roundRobin; + private readonly RoundRobin _roundRobin; private readonly List _services; private Response _hostAndPort; @@ -25,7 +25,7 @@ namespace Ocelot.UnitTests.LoadBalancer new Service("product", new HostAndPort("127.0.0.1", 5001), string.Empty, string.Empty, new string[0]) }; - _roundRobin = new RoundRobinLoadBalancer(() => Task.FromResult(_services)); + _roundRobin = new RoundRobin(() => Task.FromResult(_services)); } [Fact] diff --git a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs index 807c35a5..4c72d137 100644 --- a/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Request/HttpRequestBuilderMiddlewareTests.cs @@ -1,122 +1,122 @@ -namespace Ocelot.UnitTests.Request -{ - using System.Collections.Generic; - using System.Net.Http; - using Microsoft.Extensions.DependencyInjection; - using Moq; - using Ocelot.Configuration.Builder; - using Ocelot.DownstreamRouteFinder; - using Ocelot.DownstreamRouteFinder.UrlMatcher; - using Ocelot.Infrastructure.RequestData; - using Ocelot.Logging; - using Ocelot.Request.Builder; - using Ocelot.Request.Middleware; - using Ocelot.Responses; - using TestStack.BDDfy; - using Xunit; - using Ocelot.Requester.QoS; - using Ocelot.Configuration; +namespace Ocelot.UnitTests.Request +{ + using System.Collections.Generic; + using System.Net.Http; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using Ocelot.Configuration.Builder; + using Ocelot.DownstreamRouteFinder; + using Ocelot.DownstreamRouteFinder.UrlMatcher; + using Ocelot.Infrastructure.RequestData; + using Ocelot.Logging; + using Ocelot.Request.Builder; + using Ocelot.Request.Middleware; + using Ocelot.Responses; + using TestStack.BDDfy; + using Xunit; + using Ocelot.Requester.QoS; + using Ocelot.Configuration; using Microsoft.AspNetCore.Builder; - public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest - { - private readonly Mock _requestBuilder; - private readonly Mock _scopedRepository; - private readonly Mock _qosProviderHouse; - private readonly HttpRequestMessage _downstreamRequest; - private OkResponse _request; - private OkResponse _downstreamUrl; - private OkResponse _downstreamRoute; - - public HttpRequestBuilderMiddlewareTests() - { - _qosProviderHouse = new Mock(); - _requestBuilder = new Mock(); - _scopedRepository = new Mock(); - - _downstreamRequest = new HttpRequestMessage(); - - _scopedRepository - .Setup(sr => sr.Get("DownstreamRequest")) - .Returns(new OkResponse(_downstreamRequest)); - - GivenTheTestServerIsConfigured(); - } - - [Fact] - public void should_call_scoped_data_repository_correctly() - { - - var downstreamRoute = new DownstreamRoute(new List(), - new ReRouteBuilder() - .WithRequestIdKey("LSRequestId") - .WithUpstreamHttpMethod(new List { "Get" }) - .WithHttpHandlerOptions(new HttpHandlerOptions(true, true)) - .Build()); - - this.Given(x => x.GivenTheDownStreamUrlIs("any old string")) - .And(x => x.GivenTheQosProviderHouseReturns(new OkResponse(new NoQoSProvider()))) - .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) - .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false))) - .When(x => x.WhenICallTheMiddleware()) - .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) - .BDDfy(); - } - - protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services) - { - services.AddSingleton(); - services.AddLogging(); - services.AddSingleton(_qosProviderHouse.Object); - services.AddSingleton(_requestBuilder.Object); - services.AddSingleton(_scopedRepository.Object); - } - - protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app) - { - app.UseHttpRequestBuilderMiddleware(); - } - - private void GivenTheDownStreamUrlIs(string downstreamUrl) - { - _downstreamUrl = new OkResponse(downstreamUrl); - _scopedRepository - .Setup(x => x.Get(It.IsAny())) - .Returns(_downstreamUrl); - } - - private void GivenTheQosProviderHouseReturns(Response qosProvider) - { - _qosProviderHouse - .Setup(x => x.Get(It.IsAny())) - .Returns(qosProvider); - } - - private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) - { - _downstreamRoute = new OkResponse(downstreamRoute); - _scopedRepository - .Setup(x => x.Get(It.IsAny())) - .Returns(_downstreamRoute); - } - - private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request) - { - _request = new OkResponse(request); - - _requestBuilder - .Setup(x => x.Build(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(_request); - } - - private void ThenTheScopedDataRepositoryIsCalledCorrectly() - { - _scopedRepository - .Verify(x => x.Add("Request", _request.Data), Times.Once()); - } - } -} + public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest + { + private readonly Mock _requestBuilder; + private readonly Mock _scopedRepository; + private readonly Mock _qosProviderHouse; + private readonly HttpRequestMessage _downstreamRequest; + private OkResponse _request; + private OkResponse _downstreamUrl; + private OkResponse _downstreamRoute; + + public HttpRequestBuilderMiddlewareTests() + { + _qosProviderHouse = new Mock(); + _requestBuilder = new Mock(); + _scopedRepository = new Mock(); + + _downstreamRequest = new HttpRequestMessage(); + + _scopedRepository + .Setup(sr => sr.Get("DownstreamRequest")) + .Returns(new OkResponse(_downstreamRequest)); + + GivenTheTestServerIsConfigured(); + } + + [Fact] + public void should_call_scoped_data_repository_correctly() + { + + var downstreamRoute = new DownstreamRoute(new List(), + new ReRouteBuilder() + .WithRequestIdKey("LSRequestId") + .WithUpstreamHttpMethod(new List { "Get" }) + .WithHttpHandlerOptions(new HttpHandlerOptions(true, true)) + .Build()); + + this.Given(x => x.GivenTheDownStreamUrlIs("any old string")) + .And(x => x.GivenTheQosProviderHouseReturns(new OkResponse(new NoQoSProvider()))) + .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false))) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) + .BDDfy(); + } + + protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services) + { + services.AddSingleton(); + services.AddLogging(); + services.AddSingleton(_qosProviderHouse.Object); + services.AddSingleton(_requestBuilder.Object); + services.AddSingleton(_scopedRepository.Object); + } + + protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app) + { + app.UseHttpRequestBuilderMiddleware(); + } + + private void GivenTheDownStreamUrlIs(string downstreamUrl) + { + _downstreamUrl = new OkResponse(downstreamUrl); + _scopedRepository + .Setup(x => x.Get(It.IsAny())) + .Returns(_downstreamUrl); + } + + private void GivenTheQosProviderHouseReturns(Response qosProvider) + { + _qosProviderHouse + .Setup(x => x.Get(It.IsAny())) + .Returns(qosProvider); + } + + private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) + { + _downstreamRoute = new OkResponse(downstreamRoute); + _scopedRepository + .Setup(x => x.Get(It.IsAny())) + .Returns(_downstreamRoute); + } + + private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request) + { + _request = new OkResponse(request); + + _requestBuilder + .Setup(x => x.Build(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(_request); + } + + private void ThenTheScopedDataRepositoryIsCalledCorrectly() + { + _scopedRepository + .Verify(x => x.Add("Request", _request.Data), Times.Once()); + } + } +} diff --git a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs index 1e76a027..4756ae8f 100644 --- a/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs +++ b/test/Ocelot.UnitTests/Requester/QosProviderHouseTests.cs @@ -1,5 +1,10 @@ -using Ocelot.Requester.QoS; +using Moq; +using Ocelot.Configuration; +using Ocelot.Configuration.Builder; +using Ocelot.LoadBalancer.LoadBalancers; +using Ocelot.Requester.QoS; using Ocelot.Responses; +using Ocelot.UnitTests.LoadBalancer; using Shouldly; using TestStack.BDDfy; using Xunit; @@ -12,31 +17,32 @@ namespace Ocelot.UnitTests.Requester private readonly QosProviderHouse _qosProviderHouse; private Response _addResult; private Response _getResult; - private string _key; + private ReRoute _reRoute; + private readonly Mock _factory; public QosProviderHouseTests() { - _qosProviderHouse = new QosProviderHouse(); + _factory = new Mock(); + _qosProviderHouse = new QosProviderHouse(_factory.Object); } [Fact] - public void should_store_qos_provider() + public void should_store_qos_provider_on_first_request() { - var key = "test"; + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); - this.Given(x => x.GivenThereIsAQoSProvider(key, new FakeQoSProvider())) - .When(x => x.WhenIAddTheQoSProvider()) + this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider())) .Then(x => x.ThenItIsAdded()) .BDDfy(); } [Fact] - public void should_get_qos_provider() + public void should_not_store_qos_provider_on_first_request() { - var key = "test"; + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); - this.Given(x => x.GivenThereIsAQoSProvider(key, new FakeQoSProvider())) - .When(x => x.WhenWeGetTheQoSProvider(key)) + this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider())) + .When(x => x.WhenWeGetTheQoSProvider(reRoute)) .Then(x => x.ThenItIsReturned()) .BDDfy(); } @@ -44,14 +50,14 @@ namespace Ocelot.UnitTests.Requester [Fact] public void should_store_qos_providers_by_key() { - var key = "test"; - var keyTwo = "testTwo"; + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); + var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testTwo").Build(); - this.Given(x => x.GivenThereIsAQoSProvider(key, new FakeQoSProvider())) - .And(x => x.GivenThereIsAQoSProvider(keyTwo, new FakePollyQoSProvider())) - .When(x => x.WhenWeGetTheQoSProvider(key)) + this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider())) + .And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider())) + .When(x => x.WhenWeGetTheQoSProvider(reRoute)) .Then(x => x.ThenTheQoSProviderIs()) - .When(x => x.WhenWeGetTheQoSProvider(keyTwo)) + .When(x => x.WhenWeGetTheQoSProvider(reRouteTwo)) .Then(x => x.ThenTheQoSProviderIs()) .BDDfy(); } @@ -59,11 +65,35 @@ namespace Ocelot.UnitTests.Requester [Fact] public void should_return_error_if_no_qos_provider_with_key() { - this.When(x => x.WhenWeGetTheQoSProvider("test")) + var reRoute = new ReRouteBuilder().Build(); + + this.When(x => x.WhenWeGetTheQoSProvider(reRoute)) .Then(x => x.ThenAnErrorIsReturned()) .BDDfy(); } + [Fact] + public void should_get_new_qos_provider_if_reroute_qos_provider_has_changed() + { + var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build(); + + var reRouteTwo = new ReRouteBuilder().WithReRouteKey("test").WithIsQos(true).Build(); + + this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider())) + .When(x => x.WhenWeGetTheQoSProvider(reRoute)) + .Then(x => x.ThenTheQoSProviderIs()) + .When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(reRouteTwo)) + .Then(x => x.ThenTheQoSProviderIs()) + .BDDfy(); + } + + private void WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(ReRoute reRoute) + { + _reRoute = reRoute; + _factory.Setup(x => x.Get(_reRoute)).Returns(new FakePollyQoSProvider()); + _getResult = _qosProviderHouse.Get(_reRoute); + } + private void ThenAnErrorIsReturned() { _getResult.IsError.ShouldBeTrue(); @@ -77,31 +107,30 @@ namespace Ocelot.UnitTests.Requester private void ThenItIsAdded() { - _addResult.IsError.ShouldBe(false); - _addResult.ShouldBeOfType(); - } - - private void WhenIAddTheQoSProvider() - { - _addResult = _qosProviderHouse.Add(_key, _qoSProvider); + _getResult.IsError.ShouldBe(false); + _getResult.ShouldBeOfType>(); + _factory.Verify(x => x.Get(_reRoute), Times.Once); + _getResult.Data.ShouldBe(_qoSProvider); } - private void GivenThereIsAQoSProvider(string key, IQoSProvider qoSProvider) + private void GivenThereIsAQoSProvider(ReRoute reRoute, IQoSProvider qoSProvider) { - _key = key; + _reRoute = reRoute; _qoSProvider = qoSProvider; - WhenIAddTheQoSProvider(); + _factory.Setup(x => x.Get(_reRoute)).Returns(_qoSProvider); + _getResult = _qosProviderHouse.Get(reRoute); } - private void WhenWeGetTheQoSProvider(string key) + private void WhenWeGetTheQoSProvider(ReRoute reRoute) { - _getResult = _qosProviderHouse.Get(key); + _getResult = _qosProviderHouse.Get(reRoute); } private void ThenItIsReturned() { _getResult.Data.ShouldBe(_qoSProvider); + _factory.Verify(x => x.Get(_reRoute), Times.Once); } class FakeQoSProvider : IQoSProvider diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs index 71ed1430..f1db9f80 100644 --- a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs +++ b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderFactoryTests.cs @@ -42,7 +42,6 @@ namespace Ocelot.UnitTests.ServiceDiscovery .Build(); var serviceConfig = new ServiceProviderConfigurationBuilder() - .WithServiceDiscoveryProvider("Consul") .Build(); this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))