massive refactor to handle creating load balancer first time a re route is called

This commit is contained in:
Tom Gardham-Pallister 2017-11-08 21:26:49 +00:00
parent ab14df9127
commit e43732290a
33 changed files with 294 additions and 319 deletions

View File

@ -1,6 +1,6 @@
{ {
"projects": [ "src", "test" ], "projects": [ "src", "test" ],
"sdk": { "sdk": {
"version": "2.0.0" "version": "2.0.2"
} }
} }

View File

@ -26,13 +26,14 @@ namespace Ocelot.Configuration.Builder
private string _downstreamHost; private string _downstreamHost;
private int _downstreamPort; private int _downstreamPort;
private string _loadBalancer; private string _loadBalancer;
private ServiceProviderConfiguration _serviceProviderConfiguraion;
private bool _useQos; private bool _useQos;
private QoSOptions _qosOptions; private QoSOptions _qosOptions;
private HttpHandlerOptions _httpHandlerOptions; private HttpHandlerOptions _httpHandlerOptions;
public bool _enableRateLimiting; public bool _enableRateLimiting;
public RateLimitOptions _rateLimitOptions; public RateLimitOptions _rateLimitOptions;
private string _authenticationProviderKey; private string _authenticationProviderKey;
private bool _useServiceDiscovery;
private string _serviceName;
public ReRouteBuilder WithLoadBalancer(string loadBalancer) public ReRouteBuilder WithLoadBalancer(string loadBalancer)
{ {
@ -154,12 +155,6 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ReRouteBuilder WithServiceProviderConfiguraion(ServiceProviderConfiguration serviceProviderConfiguraion)
{
_serviceProviderConfiguraion = serviceProviderConfiguraion;
return this;
}
public ReRouteBuilder WithAuthenticationOptions(AuthenticationOptions authenticationOptions) public ReRouteBuilder WithAuthenticationOptions(AuthenticationOptions authenticationOptions)
{ {
_authenticationOptions = authenticationOptions; _authenticationOptions = authenticationOptions;
@ -190,6 +185,18 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ReRouteBuilder WithUseServiceDiscovery(bool useServiceDiscovery)
{
_useServiceDiscovery = useServiceDiscovery;
return this;
}
public ReRouteBuilder WithServiceName(string serviceName)
{
_serviceName = serviceName;
return this;
}
public ReRoute Build() public ReRoute Build()
{ {
return new ReRoute( return new ReRoute(
@ -212,12 +219,13 @@ namespace Ocelot.Configuration.Builder
_downstreamHost, _downstreamHost,
_downstreamPort, _downstreamPort,
_loadBalancerKey, _loadBalancerKey,
_serviceProviderConfiguraion,
_useQos, _useQos,
_qosOptions, _qosOptions,
_enableRateLimiting, _enableRateLimiting,
_rateLimitOptions, _rateLimitOptions,
_httpHandlerOptions); _httpHandlerOptions,
_useServiceDiscovery,
_serviceName);
} }
} }
} }

View File

@ -2,38 +2,10 @@ namespace Ocelot.Configuration.Builder
{ {
public class ServiceProviderConfigurationBuilder public class ServiceProviderConfigurationBuilder
{ {
private string _serviceName;
private string _downstreamHost;
private int _downstreamPort;
private bool _userServiceDiscovery;
private string _serviceDiscoveryProvider; private string _serviceDiscoveryProvider;
private string _serviceDiscoveryProviderHost; private string _serviceDiscoveryProviderHost;
private int _serviceDiscoveryProviderPort; 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) public ServiceProviderConfigurationBuilder WithServiceDiscoveryProvider(string serviceDiscoveryProvider)
{ {
_serviceDiscoveryProvider = serviceDiscoveryProvider; _serviceDiscoveryProvider = serviceDiscoveryProvider;
@ -52,11 +24,9 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ServiceProviderConfiguration Build() public ServiceProviderConfiguration Build()
{ {
return new ServiceProviderConfiguration(_serviceName, _downstreamHost, _downstreamPort, _userServiceDiscovery, return new ServiceProviderConfiguration(_serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort);
_serviceDiscoveryProvider, _serviceDiscoveryProviderHost,_serviceDiscoveryProviderPort);
} }
} }
} }

View File

@ -26,7 +26,6 @@ namespace Ocelot.Configuration.Creator
private readonly IOptions<FileConfiguration> _options; private readonly IOptions<FileConfiguration> _options;
private readonly IConfigurationValidator _configurationValidator; private readonly IConfigurationValidator _configurationValidator;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly ILoadBalancerCreator _lbCreator;
private readonly IQoSProviderFactory _qoSProviderFactory; private readonly IQoSProviderFactory _qoSProviderFactory;
private readonly IQosProviderHouse _qosProviderHouse; private readonly IQosProviderHouse _qosProviderHouse;
private readonly IClaimsToThingCreator _claimsToThingCreator; private readonly IClaimsToThingCreator _claimsToThingCreator;
@ -44,7 +43,6 @@ namespace Ocelot.Configuration.Creator
IOptions<FileConfiguration> options, IOptions<FileConfiguration> options,
IConfigurationValidator configurationValidator, IConfigurationValidator configurationValidator,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
ILoadBalancerCreator lbCreator,
IQoSProviderFactory qoSProviderFactory, IQoSProviderFactory qoSProviderFactory,
IQosProviderHouse qosProviderHouse, IQosProviderHouse qosProviderHouse,
IClaimsToThingCreator claimsToThingCreator, IClaimsToThingCreator claimsToThingCreator,
@ -59,7 +57,6 @@ namespace Ocelot.Configuration.Creator
IHttpHandlerOptionsCreator httpHandlerOptionsCreator IHttpHandlerOptionsCreator httpHandlerOptionsCreator
) )
{ {
_lbCreator = lbCreator;
_regionCreator = regionCreator; _regionCreator = regionCreator;
_rateLimitOptionsCreator = rateLimitOptionsCreator; _rateLimitOptionsCreator = rateLimitOptionsCreator;
_requestIdKeyCreator = requestIdKeyCreator; _requestIdKeyCreator = requestIdKeyCreator;
@ -115,7 +112,9 @@ namespace Ocelot.Configuration.Creator
reRoutes.Add(ocelotReRoute); reRoutes.Add(ocelotReRoute);
} }
return new OcelotConfiguration(reRoutes, fileConfiguration.GlobalConfiguration.AdministrationPath); var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration);
return new OcelotConfiguration(reRoutes, fileConfiguration.GlobalConfiguration.AdministrationPath, serviceProviderConfiguration);
} }
private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration) private async Task<ReRoute> SetUpReRoute(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration)
@ -128,8 +127,6 @@ namespace Ocelot.Configuration.Creator
var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute); var upstreamTemplatePattern = _upstreamTemplatePatternCreator.Create(fileReRoute);
var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileReRoute, globalConfiguration);
var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute); var authOptionsForRoute = _authOptionsCreator.Create(fileReRoute);
var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest); var claimsToHeaders = _claimsToThingCreator.Create(fileReRoute.AddHeadersToRequest);
@ -166,7 +163,6 @@ namespace Ocelot.Configuration.Creator
.WithDownstreamHost(fileReRoute.DownstreamHost) .WithDownstreamHost(fileReRoute.DownstreamHost)
.WithDownstreamPort(fileReRoute.DownstreamPort) .WithDownstreamPort(fileReRoute.DownstreamPort)
.WithLoadBalancerKey(reRouteKey) .WithLoadBalancerKey(reRouteKey)
.WithServiceProviderConfiguraion(serviceProviderConfiguration)
.WithIsQos(fileReRouteOptions.IsQos) .WithIsQos(fileReRouteOptions.IsQos)
.WithQosOptions(qosOptions) .WithQosOptions(qosOptions)
.WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting) .WithEnableRateLimiting(fileReRouteOptions.EnableRateLimiting)
@ -174,7 +170,6 @@ namespace Ocelot.Configuration.Creator
.WithHttpHandlerOptions(httpHandlerOptions) .WithHttpHandlerOptions(httpHandlerOptions)
.Build(); .Build();
await _lbCreator.SetupLoadBalancer(reRoute);
SetupQosProvider(reRoute); SetupQosProvider(reRoute);
return reRoute; return reRoute;
} }

View File

@ -4,6 +4,6 @@ namespace Ocelot.Configuration.Creator
{ {
public interface IServiceProviderConfigurationCreator public interface IServiceProviderConfigurationCreator
{ {
ServiceProviderConfiguration Create(FileReRoute fileReRoute, FileGlobalConfiguration globalConfiguration); ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfiguration);
} }
} }

View File

@ -5,18 +5,11 @@ namespace Ocelot.Configuration.Creator
{ {
public class ServiceProviderConfigurationCreator : IServiceProviderConfigurationCreator 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; var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
return new ServiceProviderConfigurationBuilder() return new ServiceProviderConfigurationBuilder()
.WithServiceName(fileReRoute.ServiceName)
.WithDownstreamHost(fileReRoute.DownstreamHost)
.WithDownstreamPort(fileReRoute.DownstreamPort)
.WithUseServiceDiscovery(useServiceDiscovery)
.WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider) .WithServiceDiscoveryProvider(globalConfiguration?.ServiceDiscoveryProvider?.Provider)
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) .WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithServiceDiscoveryProviderPort(serviceProviderPort) .WithServiceDiscoveryProviderPort(serviceProviderPort)

View File

@ -6,5 +6,6 @@ namespace Ocelot.Configuration
{ {
List<ReRoute> ReRoutes { get; } List<ReRoute> ReRoutes { get; }
string AdministrationPath {get;} string AdministrationPath {get;}
ServiceProviderConfiguration ServiceProviderConfiguration {get;}
} }
} }

View File

@ -4,13 +4,15 @@ namespace Ocelot.Configuration
{ {
public class OcelotConfiguration : IOcelotConfiguration public class OcelotConfiguration : IOcelotConfiguration
{ {
public OcelotConfiguration(List<ReRoute> reRoutes, string administrationPath) public OcelotConfiguration(List<ReRoute> reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration)
{ {
ReRoutes = reRoutes; ReRoutes = reRoutes;
AdministrationPath = administrationPath; AdministrationPath = administrationPath;
ServiceProviderConfiguration = serviceProviderConfiguration;
} }
public List<ReRoute> ReRoutes { get; } public List<ReRoute> ReRoutes { get; }
public string AdministrationPath {get;} public string AdministrationPath {get;}
public ServiceProviderConfiguration ServiceProviderConfiguration {get;}
} }
} }

View File

@ -25,15 +25,17 @@ namespace Ocelot.Configuration
string downstreamHost, string downstreamHost,
int downstreamPort, int downstreamPort,
string reRouteKey, string reRouteKey,
ServiceProviderConfiguration serviceProviderConfiguraion,
bool isQos, bool isQos,
QoSOptions qosOptions, QoSOptions qosOptions,
bool enableEndpointRateLimiting, bool enableEndpointRateLimiting,
RateLimitOptions ratelimitOptions, RateLimitOptions ratelimitOptions,
HttpHandlerOptions httpHandlerOptions) HttpHandlerOptions httpHandlerOptions,
bool useServiceDiscovery,
string serviceName)
{ {
ServiceName = serviceName;
UseServiceDiscovery = useServiceDiscovery;
ReRouteKey = reRouteKey; ReRouteKey = reRouteKey;
ServiceProviderConfiguraion = serviceProviderConfiguraion;
LoadBalancer = loadBalancer; LoadBalancer = loadBalancer;
DownstreamHost = downstreamHost; DownstreamHost = downstreamHost;
DownstreamPort = downstreamPort; DownstreamPort = downstreamPort;
@ -83,9 +85,10 @@ namespace Ocelot.Configuration
public string LoadBalancer {get;private set;} public string LoadBalancer {get;private set;}
public string DownstreamHost { get; private set; } public string DownstreamHost { get; private set; }
public int DownstreamPort { get; private set; } public int DownstreamPort { get; private set; }
public ServiceProviderConfiguration ServiceProviderConfiguraion { get; private set; }
public bool EnableEndpointEndpointRateLimiting { get; private set; } public bool EnableEndpointEndpointRateLimiting { get; private set; }
public RateLimitOptions RateLimitOptions { get; private set; } public RateLimitOptions RateLimitOptions { get; private set; }
public HttpHandlerOptions HttpHandlerOptions { get; private set; } public HttpHandlerOptions HttpHandlerOptions { get; private set; }
public bool UseServiceDiscovery {get;private set;}
public string ServiceName {get;private set;}
} }
} }

View File

@ -2,22 +2,13 @@
{ {
public class ServiceProviderConfiguration public class ServiceProviderConfiguration
{ {
public ServiceProviderConfiguration(string serviceName, string downstreamHost, public ServiceProviderConfiguration(string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort)
int downstreamPort, bool useServiceDiscovery, string serviceDiscoveryProvider, string serviceProviderHost, int serviceProviderPort)
{ {
ServiceName = serviceName;
DownstreamHost = downstreamHost;
DownstreamPort = downstreamPort;
UseServiceDiscovery = useServiceDiscovery;
ServiceDiscoveryProvider = serviceDiscoveryProvider; ServiceDiscoveryProvider = serviceDiscoveryProvider;
ServiceProviderHost = serviceProviderHost; ServiceProviderHost = serviceProviderHost;
ServiceProviderPort = serviceProviderPort; ServiceProviderPort = serviceProviderPort;
} }
public string ServiceName { get; }
public string DownstreamHost { get; }
public int DownstreamPort { get; }
public bool UseServiceDiscovery { get; }
public string ServiceDiscoveryProvider { get; } public string ServiceDiscoveryProvider { get; }
public string ServiceProviderHost { get; private set; } public string ServiceProviderHost { get; private set; }
public int ServiceProviderPort { get; private set; } public int ServiceProviderPort { get; private set; }

View File

@ -94,7 +94,6 @@ namespace Ocelot.DependencyInjection
.AddJsonFormatters(); .AddJsonFormatters();
services.AddLogging(); services.AddLogging();
services.TryAddSingleton<ILoadBalancerCreator, LoadBalancerCreator>();
services.TryAddSingleton<IRegionCreator, RegionCreator>(); services.TryAddSingleton<IRegionCreator, RegionCreator>();
services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>(); services.TryAddSingleton<IFileConfigurationRepository, FileConfigurationRepository>();
services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>(); services.TryAddSingleton<IFileConfigurationSetter, FileConfigurationSetter>();

View File

@ -1,10 +0,0 @@
using System.Threading.Tasks;
using Ocelot.Configuration;
namespace Ocelot.LoadBalancer
{
public interface ILoadBalancerCreator
{
Task SetupLoadBalancer(ReRoute reRoute);
}
}

View File

@ -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);
}
}
}

View File

@ -5,6 +5,6 @@ namespace Ocelot.LoadBalancer.LoadBalancers
{ {
public interface ILoadBalancerFactory public interface ILoadBalancerFactory
{ {
Task<ILoadBalancer> Get(ReRoute reRoute); Task<ILoadBalancer> Get(ReRoute reRoute, ServiceProviderConfiguration config);
} }
} }

View File

@ -1,10 +1,11 @@
using Ocelot.Responses; using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Responses;
namespace Ocelot.LoadBalancer.LoadBalancers namespace Ocelot.LoadBalancer.LoadBalancers
{ {
public interface ILoadBalancerHouse public interface ILoadBalancerHouse
{ {
Response<ILoadBalancer> Get(string key); Task<Response<ILoadBalancer>> Get(ReRoute reRoute, ServiceProviderConfiguration config);
Response Add(string key, ILoadBalancer loadBalancer);
} }
} }

View File

@ -12,16 +12,16 @@ namespace Ocelot.LoadBalancer.LoadBalancers
_serviceProviderFactory = serviceProviderFactory; _serviceProviderFactory = serviceProviderFactory;
} }
public async Task<ILoadBalancer> Get(ReRoute reRoute) public async Task<ILoadBalancer> Get(ReRoute reRoute, ServiceProviderConfiguration config)
{ {
var serviceProvider = _serviceProviderFactory.Get(reRoute.ServiceProviderConfiguraion); var serviceProvider = _serviceProviderFactory.Get(config, reRoute);
switch (reRoute.LoadBalancer) switch (reRoute.LoadBalancer)
{ {
case "RoundRobin": case "RoundRobin":
return new RoundRobinLoadBalancer(async () => await serviceProvider.Get()); return new RoundRobinLoadBalancer(async () => await serviceProvider.Get());
case "LeastConnection": case "LeastConnection":
return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceProviderConfiguraion.ServiceName); return new LeastConnectionLoadBalancer(async () => await serviceProvider.Get(), reRoute.ServiceName);
default: default:
return new NoLoadBalancer(await serviceProvider.Get()); return new NoLoadBalancer(await serviceProvider.Get());
} }

View File

@ -1,33 +1,58 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ocelot.Configuration;
using Ocelot.Responses; using Ocelot.Responses;
namespace Ocelot.LoadBalancer.LoadBalancers namespace Ocelot.LoadBalancer.LoadBalancers
{ {
public class LoadBalancerHouse : ILoadBalancerHouse public class LoadBalancerHouse : ILoadBalancerHouse
{ {
private readonly ILoadBalancerFactory _factory;
private readonly Dictionary<string, ILoadBalancer> _loadBalancers; private readonly Dictionary<string, ILoadBalancer> _loadBalancers;
public LoadBalancerHouse() public LoadBalancerHouse(ILoadBalancerFactory factory)
{ {
_factory = factory;
_loadBalancers = new Dictionary<string, ILoadBalancer>(); _loadBalancers = new Dictionary<string, ILoadBalancer>();
} }
public Response<ILoadBalancer> Get(string key) public async Task<Response<ILoadBalancer>> Get(ReRoute reRoute, ServiceProviderConfiguration config)
{ {
ILoadBalancer loadBalancer; try
if(_loadBalancers.TryGetValue(key, out loadBalancer))
{ {
return new OkResponse<ILoadBalancer>(_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<ILoadBalancer>(loadBalancer);
}
loadBalancer = await _factory.Get(reRoute, config);
AddLoadBalancer(reRoute.ReRouteKey, loadBalancer);
return new OkResponse<ILoadBalancer>(loadBalancer);
} }
catch(Exception ex)
return new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
{ {
new UnableToFindLoadBalancerError($"unabe to find load balancer for {key}") return new ErrorResponse<ILoadBalancer>(new List<Ocelot.Errors.Error>()
}); {
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)) if (!_loadBalancers.ContainsKey(key))
{ {
@ -36,7 +61,6 @@ namespace Ocelot.LoadBalancer.LoadBalancers
_loadBalancers.Remove(key); _loadBalancers.Remove(key);
_loadBalancers.Add(key, loadBalancer); _loadBalancers.Add(key, loadBalancer);
return new OkResponse();
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.Provider;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.Logging; using Ocelot.Logging;
@ -11,6 +12,7 @@ namespace Ocelot.LoadBalancer.Middleware
{ {
public class LoadBalancingMiddleware : OcelotMiddleware public class LoadBalancingMiddleware : OcelotMiddleware
{ {
private readonly IOcelotConfigurationProvider _configProvider;
private readonly RequestDelegate _next; private readonly RequestDelegate _next;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly ILoadBalancerHouse _loadBalancerHouse; private readonly ILoadBalancerHouse _loadBalancerHouse;
@ -18,9 +20,11 @@ namespace Ocelot.LoadBalancer.Middleware
public LoadBalancingMiddleware(RequestDelegate next, public LoadBalancingMiddleware(RequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IRequestScopedDataRepository requestScopedDataRepository, IRequestScopedDataRepository requestScopedDataRepository,
ILoadBalancerHouse loadBalancerHouse) ILoadBalancerHouse loadBalancerHouse,
IOcelotConfigurationProvider configProvider)
: base(requestScopedDataRepository) : base(requestScopedDataRepository)
{ {
_configProvider = configProvider;
_next = next; _next = next;
_logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>(); _logger = loggerFactory.CreateLogger<QueryStringBuilderMiddleware>();
_loadBalancerHouse = loadBalancerHouse; _loadBalancerHouse = loadBalancerHouse;
@ -28,7 +32,9 @@ namespace Ocelot.LoadBalancer.Middleware
public async Task Invoke(HttpContext context) 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) if(loadBalancer.IsError)
{ {
_logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error"); _logger.LogDebug("there was an error retriving the loadbalancer, setting pipeline error");

View File

@ -4,6 +4,6 @@ namespace Ocelot.ServiceDiscovery
{ {
public interface IServiceDiscoveryProviderFactory public interface IServiceDiscoveryProviderFactory
{ {
IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig); IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, ReRoute reRoute);
} }
} }

View File

@ -6,17 +6,17 @@ namespace Ocelot.ServiceDiscovery
{ {
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory 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<Service>() var services = new List<Service>()
{ {
new Service(serviceConfig.ServiceName, new Service(reRoute.ServiceName,
new HostAndPort(serviceConfig.DownstreamHost, serviceConfig.DownstreamPort), new HostAndPort(reRoute.DownstreamHost, reRoute.DownstreamPort),
string.Empty, string.Empty,
string.Empty, string.Empty,
new string[0]) new string[0])

View File

@ -3,11 +3,13 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.ServiceDiscovery; using Ocelot.ServiceDiscovery;
using TestStack.BDDfy; using TestStack.BDDfy;
@ -60,7 +62,7 @@ namespace Ocelot.AcceptanceTests
var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot"); var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot");
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl)) 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.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig)) .And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -69,6 +71,69 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_fix_issue_142()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
},
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<string> {"Get"})
.WithLoadBalancer("LeastConnection")
.WithLoadBalancerKey("/cs/status|Get")
.WithServiceName("")
.WithUseServiceDiscovery(true)
.Build();
var reRoutes = new List<ReRoute> { 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) private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url)
{ {
_fakeConsulBuilder = new WebHostBuilder() _fakeConsulBuilder = new WebHostBuilder()
@ -137,7 +202,7 @@ namespace Ocelot.AcceptanceTests
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e"; 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() _builder = new WebHostBuilder()
.UseUrls(url) .UseUrls(url)
@ -147,6 +212,8 @@ namespace Ocelot.AcceptanceTests
.UseUrls(url) .UseUrls(url)
.Configure(app => .Configure(app =>
{ {
app.UsePathBase(basePath);
app.Run(async context => app.Run(async context =>
{ {
context.Response.StatusCode = statusCode; context.Response.StatusCode = statusCode;

View File

@ -44,7 +44,6 @@ namespace Ocelot.UnitTests.Configuration
private Mock<IRateLimitOptionsCreator> _rateLimitOptions; private Mock<IRateLimitOptionsCreator> _rateLimitOptions;
private Mock<IRegionCreator> _regionCreator; private Mock<IRegionCreator> _regionCreator;
private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator; private Mock<IHttpHandlerOptionsCreator> _httpHandlerOptionsCreator;
private Mock<ILoadBalancerCreator> _lbCreator;
public FileConfigurationCreatorTests() public FileConfigurationCreatorTests()
{ {
@ -65,11 +64,9 @@ namespace Ocelot.UnitTests.Configuration
_rateLimitOptions = new Mock<IRateLimitOptionsCreator>(); _rateLimitOptions = new Mock<IRateLimitOptionsCreator>();
_regionCreator = new Mock<IRegionCreator>(); _regionCreator = new Mock<IRegionCreator>();
_httpHandlerOptionsCreator = new Mock<IHttpHandlerOptionsCreator>(); _httpHandlerOptionsCreator = new Mock<IHttpHandlerOptionsCreator>();
_lbCreator = new Mock<ILoadBalancerCreator>();
_ocelotConfigurationCreator = new FileOcelotConfigurationCreator( _ocelotConfigurationCreator = new FileOcelotConfigurationCreator(
_fileConfig.Object, _validator.Object, _logger.Object, _fileConfig.Object, _validator.Object, _logger.Object,
_lbCreator.Object,
_qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object, _qosProviderFactory.Object, _qosProviderHouse.Object, _claimsToThingCreator.Object,
_authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object, _authOptionsCreator.Object, _upstreamTemplatePatternCreator.Object, _requestIdKeyCreator.Object,
_serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object, _serviceProviderConfigCreator.Object, _qosOptionsCreator.Object, _fileReRouteOptionsCreator.Object,
@ -189,32 +186,6 @@ namespace Ocelot.UnitTests.Configuration
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_create_load_balancer()
{
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamHost = "127.0.0.1",
UpstreamPathTemplate = "/api/products/{productId}",
DownstreamPathTemplate = "/products/{productId}",
UpstreamHttpMethod = new List<string> { "Get" },
}
},
}))
.And(x => x.GivenTheConfigIsValid())
.And(x => x.GivenTheFollowingOptionsAreReturned(reRouteOptions))
.When(x => x.WhenICreateTheConfig())
.And(x => x.ThenTheLoadBalancerCreatorIsCalledCorrectly())
.BDDfy();
}
[Fact] [Fact]
public void should_use_downstream_host() public void should_use_downstream_host()
{ {
@ -320,12 +291,8 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamPathTemplate("/products/{productId}") .WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}") .WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder() .WithUseServiceDiscovery(true)
.WithUseServiceDiscovery(true) .WithServiceName("ProductService")
.WithServiceDiscoveryProvider("consul")
.WithServiceDiscoveryProviderHost("127.0.0.1")
.WithServiceName("ProductService")
.Build())
.Build() .Build()
})) }))
.BDDfy(); .BDDfy();
@ -359,9 +326,7 @@ namespace Ocelot.UnitTests.Configuration
.WithDownstreamPathTemplate("/products/{productId}") .WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}") .WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder() .WithUseServiceDiscovery(false)
.WithUseServiceDiscovery(false)
.Build())
.Build() .Build()
})) }))
.BDDfy(); .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<ReRoute> expectedReRoutes) private void ThenTheAuthenticationOptionsAre(List<ReRoute> expectedReRoutes)
{ {
for (int i = 0; i < _config.Data.ReRoutes.Count; i++) 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<ReRoute>()), Times.Once);
}
private void GivenTheQosProviderFactoryReturns() private void GivenTheQosProviderFactoryReturns()
{ {
_qosProviderFactory _qosProviderFactory

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
@ -36,7 +37,8 @@ namespace Ocelot.UnitTests.Configuration
public void should_set_configuration() public void should_set_configuration()
{ {
var fileConfig = new FileConfiguration(); var fileConfig = new FileConfiguration();
var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty); var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
var config = new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig);
this.Given(x => GivenTheFollowingConfiguration(fileConfig)) this.Given(x => GivenTheFollowingConfiguration(fileConfig))
.And(x => GivenTheRepoReturns(new OkResponse())) .And(x => GivenTheRepoReturns(new OkResponse()))

View File

@ -92,6 +92,8 @@ namespace Ocelot.UnitTests.Configuration
}; };
public string AdministrationPath {get;} public string AdministrationPath {get;}
public ServiceProviderConfiguration ServiceProviderConfiguration => throw new NotImplementedException();
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using Ocelot.Configuration.Provider; using Ocelot.Configuration.Provider;
using Ocelot.Configuration.Repository; using Ocelot.Configuration.Repository;
@ -27,9 +28,11 @@ namespace Ocelot.UnitTests.Configuration
[Fact] [Fact]
public void should_get_config() public void should_get_config()
{ {
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty)))) var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenTheRepoReturns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
.When(x => x.WhenIGetTheConfig()) .When(x => x.WhenIGetTheConfig())
.Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty)))) .Then(x => x.TheFollowingIsReturned(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(new List<ReRoute>(), string.Empty, serviceProviderConfig))))
.BDDfy(); .BDDfy();
} }

View File

@ -60,15 +60,12 @@ namespace Ocelot.UnitTests.Configuration
private void WhenICreate() private void WhenICreate()
{ {
_result = _creator.Create(_reRoute, _globalConfig); _result = _creator.Create(_globalConfig);
} }
private void ThenTheConfigIs(ServiceProviderConfiguration expected) private void ThenTheConfigIs(ServiceProviderConfiguration expected)
{ {
_result.DownstreamHost.ShouldBe(expected.DownstreamHost);
_result.DownstreamPort.ShouldBe(expected.DownstreamPort);
_result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider); _result.ServiceDiscoveryProvider.ShouldBe(expected.ServiceDiscoveryProvider);
_result.ServiceName.ShouldBe(expected.ServiceName);
_result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost); _result.ServiceProviderHost.ShouldBe(expected.ServiceProviderHost);
_result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort); _result.ServiceProviderPort.ShouldBe(expected.ServiceProviderPort);
} }

View File

@ -36,6 +36,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_return_route() public void should_return_route()
{ {
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher/"))
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>( new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
@ -48,7 +50,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath") .WithUpstreamTemplatePattern("someUpstreamPath")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -69,6 +71,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_append_slash_to_upstream_url_path() public void should_append_slash_to_upstream_url_path()
{ {
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("matchInUrlMatcher"))
.And(x =>x.GivenTheTemplateVariableAndNameFinderReturns( .And(x =>x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<UrlPathPlaceholderNameAndValue>>( new OkResponse<List<UrlPathPlaceholderNameAndValue>>(
@ -81,7 +85,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath") .WithUpstreamTemplatePattern("someUpstreamPath")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -101,6 +105,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_return_route_if_upstream_path_and_upstream_template_are_the_same() 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")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And( .And(
x => x =>
@ -114,7 +120,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("someUpstreamPath") .WithUpstreamTemplatePattern("someUpstreamPath")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -133,6 +139,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_return_correct_route_for_http_verb() public void should_return_correct_route_for_http_verb()
{ {
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And( .And(
x => x =>
@ -152,7 +160,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Post" }) .WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -170,6 +178,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_not_return_route() public void should_not_return_route()
{ {
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath/")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("dontMatchPath/"))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute> .And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{ {
@ -179,7 +189,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern("somePath") .WithUpstreamTemplatePattern("somePath")
.Build(), .Build(),
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(false))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Get")) .And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
@ -193,6 +203,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_return_correct_route_for_http_verb_setting_multiple_upstream_http_method() 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")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And( .And(
x => x =>
@ -206,7 +218,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" }) .WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -224,6 +236,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_return_correct_route_for_http_verb_setting_all_upstream_http_method() 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")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And( .And(
x => x =>
@ -237,7 +251,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string>()) .WithUpstreamHttpMethod(new List<string>())
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -255,6 +269,8 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact] [Fact]
public void should_not_return_route_for_http_verb_not_setting_in_upstream_http_method() 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")) this.Given(x => x.GivenThereIsAnUpstreamUrlPath("someUpstreamPath"))
.And( .And(
x => x =>
@ -268,7 +284,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" }) .WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
.WithUpstreamTemplatePattern("") .WithUpstreamTemplatePattern("")
.Build() .Build()
}, string.Empty }, string.Empty, serviceProviderConfig
)) ))
.And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true)))) .And(x => x.GivenTheUrlMatcherReturns(new OkResponse<UrlMatch>(new UrlMatch(true))))
.And(x => x.GivenTheUpstreamHttpMethodIs("Post")) .And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
@ -322,12 +338,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Returns(_match); .Returns(_match);
} }
private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath) private void GivenTheConfigurationIs(List<ReRoute> reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig)
{ {
_reRoutesConfig = reRoutesConfig; _reRoutesConfig = reRoutesConfig;
_mockConfig _mockConfig
.Setup(x => x.Get()) .Setup(x => x.Get())
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath))); .ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig)));
} }
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)

View File

@ -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<ILoadBalancerFactory> _factory;
private ReRoute _reRoute;
public LoadBalancerCreatorTests()
{
_house = new LoadBalancerHouse();
_factory = new Mock<ILoadBalancerFactory>();
_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<ReRoute>()))
.ReturnsAsync(new NoLoadBalancer(new List<Service>()));
}
private void WhenICallTheCreator()
{
_creator.SetupLoadBalancer(_reRoute).Wait();
}
private void ThenTheLoadBalancerIsCreated()
{
var lb = _house.Get(_reRoute.ReRouteKey);
lb.ShouldNotBeNull();
}
}
}

View File

@ -17,6 +17,7 @@ namespace Ocelot.UnitTests.LoadBalancer
private ILoadBalancer _result; private ILoadBalancer _result;
private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory; private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
private Mock<IServiceDiscoveryProvider> _serviceProvider; private Mock<IServiceDiscoveryProvider> _serviceProvider;
private ServiceProviderConfiguration _serviceProviderConfig;
public LoadBalancerFactoryTests() public LoadBalancerFactoryTests()
{ {
@ -29,11 +30,11 @@ namespace Ocelot.UnitTests.LoadBalancer
public void should_return_no_load_balancer() public void should_return_no_load_balancer()
{ {
var reRoute = new ReRouteBuilder() var reRoute = new ReRouteBuilder()
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build(); .Build();
this.Given(x => x.GivenAReRoute(reRoute)) this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns()) .And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer()) .When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>()) .Then(x => x.ThenTheLoadBalancerIsReturned<NoLoadBalancer>())
@ -46,10 +47,10 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder() var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin") .WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build(); .Build();
this.Given(x => x.GivenAReRoute(reRoute)) this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns()) .And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer()) .When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobinLoadBalancer>()) .Then(x => x.ThenTheLoadBalancerIsReturned<RoundRobinLoadBalancer>())
@ -62,10 +63,10 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder() var reRoute = new ReRouteBuilder()
.WithLoadBalancer("LeastConnection") .WithLoadBalancer("LeastConnection")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build(); .Build();
this.Given(x => x.GivenAReRoute(reRoute)) this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns()) .And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer()) .When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnectionLoadBalancer>()) .Then(x => x.ThenTheLoadBalancerIsReturned<LeastConnectionLoadBalancer>())
@ -78,27 +79,32 @@ namespace Ocelot.UnitTests.LoadBalancer
var reRoute = new ReRouteBuilder() var reRoute = new ReRouteBuilder()
.WithLoadBalancer("RoundRobin") .WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.WithServiceProviderConfiguraion(new ServiceProviderConfigurationBuilder().Build())
.Build(); .Build();
this.Given(x => x.GivenAReRoute(reRoute)) this.Given(x => x.GivenAReRoute(reRoute))
.And(x => GivenAServiceProviderConfig(new ServiceProviderConfigurationBuilder().Build()))
.And(x => x.GivenTheServiceProviderFactoryReturns()) .And(x => x.GivenTheServiceProviderFactoryReturns())
.When(x => x.WhenIGetTheLoadBalancer()) .When(x => x.WhenIGetTheLoadBalancer())
.Then(x => x.ThenTheServiceProviderIsCalledCorrectly()) .Then(x => x.ThenTheServiceProviderIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
private void GivenAServiceProviderConfig(ServiceProviderConfiguration serviceProviderConfig)
{
_serviceProviderConfig = serviceProviderConfig;
}
private void GivenTheServiceProviderFactoryReturns() private void GivenTheServiceProviderFactoryReturns()
{ {
_serviceProviderFactory _serviceProviderFactory
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>())) .Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()))
.Returns(_serviceProvider.Object); .Returns(_serviceProvider.Object);
} }
private void ThenTheServiceProviderIsCalledCorrectly() private void ThenTheServiceProviderIsCalledCorrectly()
{ {
_serviceProviderFactory _serviceProviderFactory
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>()), Times.Once); .Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()), Times.Once);
} }
private void GivenAReRoute(ReRoute reRoute) private void GivenAReRoute(ReRoute reRoute)
@ -108,7 +114,7 @@ namespace Ocelot.UnitTests.LoadBalancer
private void WhenIGetTheLoadBalancer() private void WhenIGetTheLoadBalancer()
{ {
_result = _factory.Get(_reRoute).Result; _result = _factory.Get(_reRoute, _serviceProviderConfig).Result;
} }
private void ThenTheLoadBalancerIsReturned<T>() private void ThenTheLoadBalancerIsReturned<T>()

View File

@ -1,5 +1,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.LoadBalancer.LoadBalancers; using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.Responses; using Ocelot.Responses;
using Ocelot.Values; using Ocelot.Values;
@ -11,35 +14,38 @@ namespace Ocelot.UnitTests.LoadBalancer
{ {
public class LoadBalancerHouseTests public class LoadBalancerHouseTests
{ {
private ReRoute _reRoute;
private ILoadBalancer _loadBalancer; private ILoadBalancer _loadBalancer;
private readonly LoadBalancerHouse _loadBalancerHouse; private readonly LoadBalancerHouse _loadBalancerHouse;
private Response _addResult; private Response _addResult;
private Response<ILoadBalancer> _getResult; private Response<ILoadBalancer> _getResult;
private string _key; private string _key;
private Mock<ILoadBalancerFactory> _factory;
private ServiceProviderConfiguration _serviceProviderConfig;
public LoadBalancerHouseTests() public LoadBalancerHouseTests()
{ {
_loadBalancerHouse = new LoadBalancerHouse(); _factory = new Mock<ILoadBalancerFactory>();
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
} }
[Fact] [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())) this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenIAddTheLoadBalancer())
.Then(x => x.ThenItIsAdded()) .Then(x => x.ThenItIsAdded())
.BDDfy(); .BDDfy();
} }
[Fact] [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())) this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(key)) .When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenItIsReturned()) .Then(x => x.ThenItIsReturned())
.BDDfy(); .BDDfy();
} }
@ -47,26 +53,50 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact] [Fact]
public void should_store_load_balancers_by_key() public void should_store_load_balancers_by_key()
{ {
var key = "test"; var reRoute = new ReRouteBuilder().WithLoadBalancerKey("test").Build();
var keyTwo = "testTwo"; var reRouteTwo = new ReRouteBuilder().WithLoadBalancerKey("testtwo").Build();
this.Given(x => x.GivenThereIsALoadBalancer(key, new FakeLoadBalancer())) this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.And(x => x.GivenThereIsALoadBalancer(keyTwo, new FakeRoundRobinLoadBalancer())) .And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(key)) .When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>()) .Then(x => x.ThenTheLoadBalancerIs<FakeLoadBalancer>())
.When(x => x.WhenWeGetTheLoadBalancer(keyTwo)) .When(x => x.WhenWeGetTheLoadBalancer(reRouteTwo))
.Then(x => x.ThenTheLoadBalancerIs<FakeRoundRobinLoadBalancer>()) .Then(x => x.ThenTheLoadBalancerIs<FakeRoundRobinLoadBalancer>())
.BDDfy(); .BDDfy();
} }
[Fact] [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()) .Then(x => x.ThenAnErrorIsReturned())
.BDDfy(); .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<FakeLoadBalancer>())
.When(x => x.WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(reRouteTwo))
.Then(x => x.ThenTheLoadBalancerIs<LeastConnectionLoadBalancer>())
.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() private void ThenAnErrorIsReturned()
{ {
_getResult.IsError.ShouldBeTrue(); _getResult.IsError.ShouldBeTrue();
@ -80,31 +110,30 @@ namespace Ocelot.UnitTests.LoadBalancer
private void ThenItIsAdded() private void ThenItIsAdded()
{ {
_addResult.IsError.ShouldBe(false); _getResult.IsError.ShouldBe(false);
_addResult.ShouldBeOfType<OkResponse>(); _getResult.ShouldBeOfType<OkResponse<ILoadBalancer>>();
} _getResult.Data.ShouldBe(_loadBalancer);
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
private void WhenIAddTheLoadBalancer()
{
_addResult = _loadBalancerHouse.Add(_key, _loadBalancer);
} }
private void GivenThereIsALoadBalancer(string key, ILoadBalancer loadBalancer) private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer)
{ {
_key = key; _reRoute = reRoute;
_loadBalancer = loadBalancer; _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() private void ThenItIsReturned()
{ {
_getResult.Data.ShouldBe(_loadBalancer); _getResult.Data.ShouldBe(_loadBalancer);
_factory.Verify(x => x.Get(_reRoute, _serviceProviderConfig), Times.Once);
} }
class FakeLoadBalancer : ILoadBalancer class FakeLoadBalancer : ILoadBalancer

View File

@ -5,6 +5,7 @@ namespace Ocelot.UnitTests.LoadBalancer
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Moq; using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.Errors; using Ocelot.Errors;
@ -137,8 +138,8 @@ namespace Ocelot.UnitTests.LoadBalancer
private void GivenTheLoadBalancerHouseReturns() private void GivenTheLoadBalancerHouseReturns()
{ {
_loadBalancerHouse _loadBalancerHouse
.Setup(x => x.Get(It.IsAny<string>())) .Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.Returns(new OkResponse<ILoadBalancer>(_loadBalancer.Object)); .ReturnsAsync(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
} }
private void GivenTheLoadBalancerHouseReturnsAnError() private void GivenTheLoadBalancerHouseReturnsAnError()
@ -149,8 +150,8 @@ namespace Ocelot.UnitTests.LoadBalancer
}); });
_loadBalancerHouse _loadBalancerHouse
.Setup(x => x.Get(It.IsAny<string>())) .Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.Returns(_getLoadBalancerHouseError); .ReturnsAsync(_getLoadBalancerHouseError);
} }
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline() private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()

View File

@ -12,6 +12,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private ServiceProviderConfiguration _serviceConfig; private ServiceProviderConfiguration _serviceConfig;
private IServiceDiscoveryProvider _result; private IServiceDiscoveryProvider _result;
private readonly ServiceDiscoveryProviderFactory _factory; private readonly ServiceDiscoveryProviderFactory _factory;
private ReRoute _reRoute;
public ServiceProviderFactoryTests() public ServiceProviderFactoryTests()
{ {
@ -22,12 +23,11 @@ namespace Ocelot.UnitTests.ServiceDiscovery
public void should_return_no_service_provider() public void should_return_no_service_provider()
{ {
var serviceConfig = new ServiceProviderConfigurationBuilder() var serviceConfig = new ServiceProviderConfigurationBuilder()
.WithDownstreamHost("127.0.0.1")
.WithDownstreamPort(80)
.WithUseServiceDiscovery(false)
.Build(); .Build();
this.Given(x => x.GivenTheReRoute(serviceConfig)) var reRoute = new ReRouteBuilder().Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider()) .When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConfigurationServiceProvider>()) .Then(x => x.ThenTheServiceProviderIs<ConfigurationServiceProvider>())
.BDDfy(); .BDDfy();
@ -36,26 +36,30 @@ namespace Ocelot.UnitTests.ServiceDiscovery
[Fact] [Fact]
public void should_return_consul_service_provider() public void should_return_consul_service_provider()
{ {
var serviceConfig = new ServiceProviderConfigurationBuilder() var reRoute = new ReRouteBuilder()
.WithServiceName("product") .WithServiceName("product")
.WithUseServiceDiscovery(true) .WithUseServiceDiscovery(true)
.Build();
var serviceConfig = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProvider("Consul") .WithServiceDiscoveryProvider("Consul")
.Build(); .Build();
this.Given(x => x.GivenTheReRoute(serviceConfig)) this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider()) .When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConsulServiceDiscoveryProvider>()) .Then(x => x.ThenTheServiceProviderIs<ConsulServiceDiscoveryProvider>())
.BDDfy(); .BDDfy();
} }
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig) private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig, ReRoute reRoute)
{ {
_serviceConfig = serviceConfig; _serviceConfig = serviceConfig;
_reRoute = reRoute;
} }
private void WhenIGetTheServiceProvider() private void WhenIGetTheServiceProvider()
{ {
_result = _factory.Get(_serviceConfig); _result = _factory.Get(_serviceConfig, _reRoute);
} }
private void ThenTheServiceProviderIs<T>() private void ThenTheServiceProviderIs<T>()