diff --git a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs index 827dcbad..61c61fae 100644 --- a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs @@ -27,13 +27,19 @@ namespace Ocelot.Configuration.Creator private readonly IClaimToThingConfigurationParser _claimToThingConfigurationParser; private readonly ILogger _logger; + private readonly ILoadBalancerFactory _loadBalanceFactory; + private readonly ILoadBalancerHouse _loadBalancerHouse; public FileOcelotConfigurationCreator( IOptions options, IConfigurationValidator configurationValidator, IClaimToThingConfigurationParser claimToThingConfigurationParser, - ILogger logger) + ILogger logger, + ILoadBalancerFactory loadBalancerFactory, + ILoadBalancerHouse loadBalancerHouse) { + _loadBalanceFactory = loadBalancerFactory; + _loadBalancerHouse = loadBalancerHouse; _options = options; _configurationValidator = configurationValidator; _claimToThingConfigurationParser = claimToThingConfigurationParser; @@ -78,55 +84,62 @@ namespace Ocelot.Configuration.Creator return new OcelotConfiguration(reRoutes); } - private ReRoute SetUpReRoute(FileReRoute reRoute, FileGlobalConfiguration globalConfiguration) + private ReRoute SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) { var globalRequestIdConfiguration = !string.IsNullOrEmpty(globalConfiguration?.RequestIdKey); - var upstreamTemplate = BuildUpstreamTemplate(reRoute); + var upstreamTemplate = BuildUpstreamTemplate(fileReRoute); - var isAuthenticated = !string.IsNullOrEmpty(reRoute.AuthenticationOptions?.Provider); + var isAuthenticated = !string.IsNullOrEmpty(fileReRoute.AuthenticationOptions?.Provider); - var isAuthorised = reRoute.RouteClaimsRequirement?.Count > 0; + var isAuthorised = fileReRoute.RouteClaimsRequirement?.Count > 0; - var isCached = reRoute.FileCacheOptions.TtlSeconds > 0; + var isCached = fileReRoute.FileCacheOptions.TtlSeconds > 0; var requestIdKey = globalRequestIdConfiguration ? globalConfiguration.RequestIdKey - : reRoute.RequestIdKey; + : fileReRoute.RequestIdKey; - var useServiceDiscovery = !string.IsNullOrEmpty(reRoute.ServiceName) + var useServiceDiscovery = !string.IsNullOrEmpty(fileReRoute.ServiceName) && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Address) && !string.IsNullOrEmpty(globalConfiguration?.ServiceDiscoveryProvider?.Provider); + ReRoute reRoute; + if (isAuthenticated) { - var authOptionsForRoute = new AuthenticationOptions(reRoute.AuthenticationOptions.Provider, - reRoute.AuthenticationOptions.ProviderRootUrl, reRoute.AuthenticationOptions.ScopeName, - reRoute.AuthenticationOptions.RequireHttps, reRoute.AuthenticationOptions.AdditionalScopes, - reRoute.AuthenticationOptions.ScopeSecret); + var authOptionsForRoute = new AuthenticationOptions(fileReRoute.AuthenticationOptions.Provider, + fileReRoute.AuthenticationOptions.ProviderRootUrl, fileReRoute.AuthenticationOptions.ScopeName, + fileReRoute.AuthenticationOptions.RequireHttps, fileReRoute.AuthenticationOptions.AdditionalScopes, + fileReRoute.AuthenticationOptions.ScopeSecret); - var claimsToHeaders = GetAddThingsToRequest(reRoute.AddHeadersToRequest); - var claimsToClaims = GetAddThingsToRequest(reRoute.AddClaimsToRequest); - var claimsToQueries = GetAddThingsToRequest(reRoute.AddQueriesToRequest); + var claimsToHeaders = GetAddThingsToRequest(fileReRoute.AddHeadersToRequest); + var claimsToClaims = GetAddThingsToRequest(fileReRoute.AddClaimsToRequest); + var claimsToQueries = GetAddThingsToRequest(fileReRoute.AddQueriesToRequest); - return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate, - reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, + reRoute = new ReRoute(new DownstreamPathTemplate(fileReRoute.DownstreamPathTemplate), fileReRoute.UpstreamTemplate, + fileReRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, authOptionsForRoute, claimsToHeaders, claimsToClaims, - reRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries, - requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), - reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, - globalConfiguration?.ServiceDiscoveryProvider?.Address, reRoute.DownstreamScheme, - reRoute.LoadBalancer, reRoute.DownstreamHost, reRoute.DownstreamPort); + fileReRoute.RouteClaimsRequirement, isAuthorised, claimsToQueries, + requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds), + fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, + globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme, + fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort); } - return new ReRoute(new DownstreamPathTemplate(reRoute.DownstreamPathTemplate), reRoute.UpstreamTemplate, - reRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, + reRoute = new ReRoute(new DownstreamPathTemplate(fileReRoute.DownstreamPathTemplate), fileReRoute.UpstreamTemplate, + fileReRoute.UpstreamHttpMethod, upstreamTemplate, isAuthenticated, null, new List(), new List(), - reRoute.RouteClaimsRequirement, isAuthorised, new List(), - requestIdKey, isCached, new CacheOptions(reRoute.FileCacheOptions.TtlSeconds), - reRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, - globalConfiguration?.ServiceDiscoveryProvider?.Address, reRoute.DownstreamScheme, - reRoute.LoadBalancer, reRoute.DownstreamHost, reRoute.DownstreamPort); + fileReRoute.RouteClaimsRequirement, isAuthorised, new List(), + requestIdKey, isCached, new CacheOptions(fileReRoute.FileCacheOptions.TtlSeconds), + fileReRoute.ServiceName, useServiceDiscovery, globalConfiguration?.ServiceDiscoveryProvider?.Provider, + globalConfiguration?.ServiceDiscoveryProvider?.Address, fileReRoute.DownstreamScheme, + fileReRoute.LoadBalancer, fileReRoute.DownstreamHost, fileReRoute.DownstreamPort); + + var loadBalancer = _loadBalanceFactory.Get(reRoute); + //todo - not sure if this is the correct key, but this is probably the only unique key i can think of + _loadBalancerHouse.Add($"{fileReRoute.UpstreamTemplate}{fileReRoute.UpstreamHttpMethod}", loadBalancer); + return reRoute; } private string BuildUpstreamTemplate(FileReRoute reRoute) diff --git a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs index 9f40b009..86564f92 100644 --- a/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Ocelot/DependencyInjection/ServiceCollectionExtensions.cs @@ -23,11 +23,13 @@ using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.Headers; using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.RequestData; +using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.Logging; using Ocelot.QueryStrings; using Ocelot.Request.Builder; using Ocelot.Requester; using Ocelot.Responder; +using Ocelot.ServiceDiscovery; namespace Ocelot.DependencyInjection { @@ -59,6 +61,10 @@ namespace Ocelot.DependencyInjection { services.AddMvcCore().AddJsonFormatters(); services.AddLogging(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs index 930a5211..55089cde 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/ILoadBalancerFactory.cs @@ -1,7 +1,9 @@ -namespace Ocelot.LoadBalancer.LoadBalancers +using Ocelot.Configuration; + +namespace Ocelot.LoadBalancer.LoadBalancers { public interface ILoadBalancerFactory { - ILoadBalancer Get(string serviceName, string loadBalancer); + ILoadBalancer Get(ReRoute reRoute); } } \ No newline at end of file diff --git a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs index d5203062..7e11df39 100644 --- a/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs +++ b/src/Ocelot/LoadBalancer/LoadBalancers/LoadBalancerFactory.cs @@ -1,26 +1,34 @@ -using Ocelot.ServiceDiscovery; +using Ocelot.Configuration; +using Ocelot.ServiceDiscovery; namespace Ocelot.LoadBalancer.LoadBalancers { public class LoadBalancerFactory : ILoadBalancerFactory { - private readonly IServiceProvider _serviceProvider; - - public LoadBalancerFactory(IServiceProvider serviceProvider) + private readonly IServiceProviderFactory _serviceProviderFactory; + public LoadBalancerFactory(IServiceProviderFactory serviceProviderFactory) { - _serviceProvider = serviceProvider; + _serviceProviderFactory = serviceProviderFactory; } - public ILoadBalancer Get(string serviceName, string loadBalancer) + public ILoadBalancer Get(ReRoute reRoute) { - switch (loadBalancer) + var serviceConfig = new ServiceConfiguraion( + reRoute.ServiceName, + reRoute.DownstreamHost, + reRoute.DownstreamPort, + reRoute.UseServiceDiscovery); + + var serviceProvider = _serviceProviderFactory.Get(serviceConfig); + + switch (reRoute.LoadBalancer) { case "RoundRobin": - return new RoundRobinLoadBalancer(_serviceProvider.Get()); + return new RoundRobinLoadBalancer(serviceProvider.Get()); case "LeastConnection": - return new LeastConnectionLoadBalancer(() => _serviceProvider.Get(), serviceName); + return new LeastConnectionLoadBalancer(() => serviceProvider.Get(), reRoute.ServiceName); default: - return new NoLoadBalancer(_serviceProvider.Get()); + return new NoLoadBalancer(serviceProvider.Get()); } } } diff --git a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs index 5c66e98a..e762186d 100644 --- a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs +++ b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddleware.cs @@ -14,37 +14,30 @@ namespace Ocelot.LoadBalancer.Middleware { private readonly RequestDelegate _next; private readonly IOcelotLogger _logger; + private readonly ILoadBalancerHouse _loadBalancerHouse; public LoadBalancingMiddleware(RequestDelegate next, IOcelotLoggerFactory loggerFactory, - IRequestScopedDataRepository requestScopedDataRepository) + IRequestScopedDataRepository requestScopedDataRepository, + ILoadBalancerHouse loadBalancerHouse) : base(requestScopedDataRepository) { _next = next; _logger = loggerFactory.CreateLogger(); + _loadBalancerHouse = loadBalancerHouse; } public async Task Invoke(HttpContext context) { _logger.LogDebug("started calling query string builder middleware"); - //todo - get out of di? or do this when we bootstrap? - var serviceProviderFactory = new ServiceProviderFactory(); - var serviceConfig = new ServiceConfiguraion( - DownstreamRoute.ReRoute.ServiceName, - DownstreamRoute.ReRoute.DownstreamHost, - DownstreamRoute.ReRoute.DownstreamPort, - DownstreamRoute.ReRoute.UseServiceDiscovery); - //todo - get this out of some kind of service provider house? - var serviceProvider = serviceProviderFactory.Get(serviceConfig); - - //todo - get out of di? or do this when we bootstrap? - var loadBalancerFactory = new LoadBalancerFactory(serviceProvider); - //todo - currently instanciates a load balancer per request which is wrong, - //need some kind of load balance house! :) - var loadBalancer = loadBalancerFactory.Get(DownstreamRoute.ReRoute.ServiceName, DownstreamRoute.ReRoute.LoadBalancer); - var response = loadBalancer.Lease(); - + var loadBalancer = _loadBalancerHouse.Get($"{DownstreamRoute.ReRoute.UpstreamTemplate}{DownstreamRoute.ReRoute.UpstreamHttpMethod}"); + //todo check reponse and return error + + var response = loadBalancer.Data.Lease(); + //todo check reponse and return error + + SetHostAndPortForThisRequest(response.Data); _logger.LogDebug("calling next middleware"); //todo - try next middleware if we get an exception make sure we release @@ -53,11 +46,11 @@ namespace Ocelot.LoadBalancer.Middleware { await _next.Invoke(context); - loadBalancer.Release(response.Data); + loadBalancer.Data.Release(response.Data); } - catch (Exception exception) + catch (Exception) { - loadBalancer.Release(response.Data); + loadBalancer.Data.Release(response.Data); throw; } diff --git a/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddlewareExtensions.cs b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddlewareExtensions.cs new file mode 100644 index 00000000..52d47bdd --- /dev/null +++ b/src/Ocelot/LoadBalancer/Middleware/LoadBalancingMiddlewareExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Builder; + +namespace Ocelot.LoadBalancer.Middleware +{ + public static class LoadBalancingMiddlewareExtensions + { + public static IApplicationBuilder UseLoadBalancingMiddlewareExtensions(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } + } +} \ No newline at end of file diff --git a/src/Ocelot/Middleware/OcelotMiddleware.cs b/src/Ocelot/Middleware/OcelotMiddleware.cs index 0bb51040..b8937108 100644 --- a/src/Ocelot/Middleware/OcelotMiddleware.cs +++ b/src/Ocelot/Middleware/OcelotMiddleware.cs @@ -3,6 +3,7 @@ using System.Net.Http; using Ocelot.DownstreamRouteFinder; using Ocelot.Errors; using Ocelot.Infrastructure.RequestData; +using Ocelot.Values; namespace Ocelot.Middleware { @@ -69,6 +70,20 @@ namespace Ocelot.Middleware } } + public HostAndPort HostAndPort + { + get + { + var hostAndPort = _requestScopedDataRepository.Get("HostAndPort"); + return hostAndPort.Data; + } + } + + public void SetHostAndPortForThisRequest(HostAndPort hostAndPort) + { + _requestScopedDataRepository.Add("HostAndPort", hostAndPort); + } + public void SetDownstreamRouteForThisRequest(DownstreamRoute downstreamRoute) { _requestScopedDataRepository.Add("DownstreamRoute", downstreamRoute); diff --git a/src/Ocelot/ServiceDiscovery/IServiceProviderFactory.cs b/src/Ocelot/ServiceDiscovery/IServiceProviderFactory.cs index 67b84c69..62c55f53 100644 --- a/src/Ocelot/ServiceDiscovery/IServiceProviderFactory.cs +++ b/src/Ocelot/ServiceDiscovery/IServiceProviderFactory.cs @@ -1,3 +1,5 @@ +using System; + namespace Ocelot.ServiceDiscovery { public interface IServiceProviderFactory diff --git a/src/Ocelot/ServiceDiscovery/IServiceProviderHouse.cs b/src/Ocelot/ServiceDiscovery/IServiceProviderHouse.cs deleted file mode 100644 index 0f85f528..00000000 --- a/src/Ocelot/ServiceDiscovery/IServiceProviderHouse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using Ocelot.Responses; - -namespace Ocelot.ServiceDiscovery -{ - public interface IServiceProviderHouse - { - Response Get(string key); - Response Add(string key, IServiceProvider serviceProvider); - } -} \ No newline at end of file diff --git a/src/Ocelot/ServiceDiscovery/ServiceProviderHouse.cs b/src/Ocelot/ServiceDiscovery/ServiceProviderHouse.cs deleted file mode 100644 index 63d14dce..00000000 --- a/src/Ocelot/ServiceDiscovery/ServiceProviderHouse.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using Ocelot.Responses; - -namespace Ocelot.ServiceDiscovery -{ - public class ServiceProviderHouse : IServiceProviderHouse - { - private Dictionary _serviceProviders; - - public ServiceProviderHouse() - { - _serviceProviders = new Dictionary(); - } - - public Response Get(string key) - { - IServiceProvider serviceProvider; - if(_serviceProviders.TryGetValue(key, out serviceProvider)) - { - return new OkResponse(serviceProvider); - } - - return new ErrorResponse(new List() - { - new UnableToFindServiceProviderError($"unabe to find service provider for {key}") - }); - } - public Response Add(string key, IServiceProvider serviceProvider) - { - _serviceProviders[key] = serviceProvider; - return new OkResponse(); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index fc80a478..b6e28033 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -8,6 +8,7 @@ using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; using Ocelot.Configuration.Parser; using Ocelot.Configuration.Validator; +using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.Responses; using Shouldly; using TestStack.BDDfy; @@ -24,6 +25,8 @@ namespace Ocelot.UnitTests.Configuration private readonly Mock _configParser; private readonly Mock> _logger; private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator; + private readonly Mock _loadBalancerFactory; + private readonly Mock _loadBalancerHouse; public FileConfigurationCreatorTests() { @@ -32,7 +35,8 @@ namespace Ocelot.UnitTests.Configuration _validator = new Mock(); _fileConfig = new Mock>(); _ocelotConfigurationCreator = new FileOcelotConfigurationCreator( - _fileConfig.Object, _validator.Object, _configParser.Object, _logger.Object); + _fileConfig.Object, _validator.Object, _configParser.Object, _logger.Object, + _loadBalancerFactory.Object, _loadBalancerHouse.Object); } [Fact] diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs index c4eb736b..7361c726 100644 --- a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerFactoryTests.cs @@ -14,12 +14,12 @@ namespace Ocelot.UnitTests.LoadBalancer private ReRoute _reRoute; private LoadBalancerFactory _factory; private ILoadBalancer _result; - private Mock _serviceProvider; + private Mock _serviceProviderFactory; public LoadBalancerFactoryTests() { - _serviceProvider = new Mock(); - _factory = new LoadBalancerFactory(_serviceProvider.Object); + _serviceProviderFactory = new Mock(); + _factory = new LoadBalancerFactory(_serviceProviderFactory.Object); } [Fact] @@ -75,8 +75,8 @@ namespace Ocelot.UnitTests.LoadBalancer private void ThenTheServiceProviderIsCalledCorrectly() { - _serviceProvider - .Verify(x => x.Get(), Times.Once); + _serviceProviderFactory + .Verify(x => x.Get(It.IsAny()), Times.Once); } private void GivenAReRoute(ReRoute reRoute) @@ -86,7 +86,7 @@ namespace Ocelot.UnitTests.LoadBalancer private void WhenIGetTheLoadBalancer() { - _result = _factory.Get(_reRoute.ServiceName, _reRoute.LoadBalancer); + _result = _factory.Get(_reRoute); } private void ThenTheLoadBalancerIsReturned() diff --git a/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs new file mode 100644 index 00000000..ed6d30c0 --- /dev/null +++ b/test/Ocelot.UnitTests/LoadBalancer/LoadBalancerMiddlewareTests.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Moq; +using Ocelot.Configuration.Builder; +using Ocelot.DownstreamRouteFinder; +using Ocelot.Infrastructure.RequestData; +using Ocelot.LoadBalancer.LoadBalancers; +using Ocelot.LoadBalancer.Middleware; +using Ocelot.Logging; +using Ocelot.Responses; +using Ocelot.Values; +using TestStack.BDDfy; +using Xunit; + +namespace Ocelot.UnitTests.LoadBalancer +{ + public class LoadBalancerMiddlewareTests + { + private readonly Mock _loadBalancerHouse; + private readonly Mock _scopedRepository; + private readonly Mock _loadBalancer; + private readonly string _url; + private readonly TestServer _server; + private readonly HttpClient _client; + private HttpResponseMessage _result; + private OkResponse _request; + private OkResponse _downstreamUrl; + private OkResponse _downstreamRoute; + + public LoadBalancerMiddlewareTests() + { + _url = "http://localhost:51879"; + _loadBalancerHouse = new Mock(); + _scopedRepository = new Mock(); + var builder = new WebHostBuilder() + .ConfigureServices(x => + { + x.AddSingleton(); + x.AddLogging(); + x.AddSingleton(_loadBalancerHouse.Object); + x.AddSingleton(_scopedRepository.Object); + }) + .UseUrls(_url) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseUrls(_url) + .Configure(app => + { + app.UseLoadBalancingMiddlewareExtensions(); + }); + + _server = new TestServer(builder); + _client = _server.CreateClient(); + } + + [Fact] + public void should_call_scoped_data_repository_correctly() + { + var downstreamRoute = new DownstreamRoute(new List(), + new ReRouteBuilder() + .Build()); + + this.Given(x => x.GivenTheDownStreamUrlIs("any old string")) + .And(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) + .And(x => x.GivenTheLoadBalancerHouseReturns()) + .And(x => x.GivenTheLoadBalancerReturns()) + .When(x => x.WhenICallTheMiddleware()) + .Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly()) + .BDDfy(); + } + + private void GivenTheLoadBalancerReturns() + { + _loadBalancer + .Setup(x => x.Lease()) + .Returns(new OkResponse(new HostAndPort("127.0.0.1", 80))); + } + + private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) + { + _downstreamRoute = new OkResponse(downstreamRoute); + _scopedRepository + .Setup(x => x.Get(It.IsAny())) + .Returns(_downstreamRoute); + } + + private void GivenTheLoadBalancerHouseReturns() + { + _loadBalancerHouse + .Setup(x => x.Get(It.IsAny())) + .Returns(new OkResponse(_loadBalancer.Object)); + } + + private void ThenTheScopedDataRepositoryIsCalledCorrectly() + { + _scopedRepository + .Verify(x => x.Add("Request", _request.Data), Times.Once()); + } + + private void WhenICallTheMiddleware() + { + _result = _client.GetAsync(_url).Result; + } + + private void GivenTheDownStreamUrlIs(string downstreamUrl) + { + _downstreamUrl = new OkResponse(downstreamUrl); + _scopedRepository + .Setup(x => x.Get(It.IsAny())) + .Returns(_downstreamUrl); + } + + public void Dispose() + { + _client.Dispose(); + _server.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderHouseTests.cs b/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderHouseTests.cs deleted file mode 100644 index 9443c113..00000000 --- a/test/Ocelot.UnitTests/ServiceDiscovery/ServiceProviderHouseTests.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using Ocelot.LoadBalancer.LoadBalancers; -using Ocelot.Responses; -using Ocelot.ServiceDiscovery; -using Ocelot.Values; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.LoadBalancer -{ - public class ServiceProviderHouseTests - { - private Ocelot.ServiceDiscovery.IServiceProvider _serviceProvider; - private readonly ServiceProviderHouse _serviceProviderHouse; - private Response _addResult; - private Response _getResult; - private string _key; - - public ServiceProviderHouseTests() - { - _serviceProviderHouse = new ServiceProviderHouse(); - } - - [Fact] - public void should_store_service_provider() - { - var key = "test"; - - this.Given(x => x.GivenThereIsAServiceProvider(key, new FakeServiceProvider())) - .When(x => x.WhenIAddTheServiceProvider()) - .Then(x => x.ThenItIsAdded()) - .BDDfy(); - } - - [Fact] - public void should_get_service_provider() - { - var key = "test"; - - this.Given(x => x.GivenThereIsAServiceProvider(key, new FakeServiceProvider())) - .When(x => x.WhenWeGetTheServiceProvider(key)) - .Then(x => x.ThenItIsReturned()) - .BDDfy(); - } - - [Fact] - public void should_store_service_providers_by_key() - { - var key = "test"; - var keyTwo = "testTwo"; - - this.Given(x => x.GivenThereIsAServiceProvider(key, new FakeServiceProvider())) - .And(x => x.GivenThereIsAServiceProvider(keyTwo, new FakeConsulServiceProvider())) - .When(x => x.WhenWeGetTheServiceProvider(key)) - .Then(x => x.ThenTheServiceProviderIs()) - .When(x => x.WhenWeGetTheServiceProvider(keyTwo)) - .Then(x => x.ThenTheServiceProviderIs()) - .BDDfy(); - } - - [Fact] - public void should_return_error_if_no_service_provider_house_with_key() - { - this.When(x => x.WhenWeGetTheServiceProvider("test")) - .Then(x => x.ThenAnErrorIsReturned()) - .BDDfy(); - } - - private void ThenAnErrorIsReturned() - { - _getResult.IsError.ShouldBeTrue(); - _getResult.Errors[0].ShouldBeOfType(); - } - - private void ThenTheServiceProviderIs() - { - _getResult.Data.ShouldBeOfType(); - } - - private void ThenItIsAdded() - { - _addResult.IsError.ShouldBe(false); - _addResult.ShouldBeOfType(); - } - - private void WhenIAddTheServiceProvider() - { - _addResult = _serviceProviderHouse.Add(_key, _serviceProvider); - } - - private void GivenThereIsAServiceProvider(string key, Ocelot.ServiceDiscovery.IServiceProvider serviceProvider) - { - _key = key; - _serviceProvider = serviceProvider; - WhenIAddTheServiceProvider(); - } - - private void WhenWeGetTheServiceProvider(string key) - { - _getResult = _serviceProviderHouse.Get(key); - } - - private void ThenItIsReturned() - { - _getResult.Data.ShouldBe(_serviceProvider); - } - - class FakeServiceProvider : Ocelot.ServiceDiscovery.IServiceProvider - { - public List Get() - { - throw new NotImplementedException(); - } - } - - class FakeConsulServiceProvider : Ocelot.ServiceDiscovery.IServiceProvider - { - public List Get() - { - throw new NotImplementedException(); - } - } - } -}