Feature/#295 consul acl (#307)

* removed file

* updated package

* updated package

* updated package

* updated package

* updated package

* updated package

* updated package

* all packages updated

* #295 can add token to service provider config and this will be used by consul clients to get services and configuration

* #295 wait longer for this test
This commit is contained in:
Tom Pallister 2018-04-08 15:54:58 +01:00 committed by GitHub
parent d7ef956935
commit 982eebfc74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 345 additions and 908 deletions

View File

@ -38,3 +38,18 @@ and LeastConnection algorithm you can use. If no load balancer is specified Ocel
} }
When this is set up Ocelot will lookup the downstream host and port from the service discover provider and load balance requests across any available services. When this is set up Ocelot will lookup the downstream host and port from the service discover provider and load balance requests across any available services.
ACL Token
---------
If you are using ACL with Consul Ocelot supports adding the X-Consul-Token header. In order so this to work you must add the additional property below.
.. code-block:: json
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 9500,
"Token": "footoken"
}
Ocelot will add this token to the consul client that it uses to make requests and that is then used for every request.

View File

@ -5,28 +5,35 @@ namespace Ocelot.Configuration.Builder
private string _serviceDiscoveryProviderHost; private string _serviceDiscoveryProviderHost;
private int _serviceDiscoveryProviderPort; private int _serviceDiscoveryProviderPort;
private string _type; private string _type;
private string _token;
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost) public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost)
{ {
_serviceDiscoveryProviderHost = serviceDiscoveryProviderHost; _serviceDiscoveryProviderHost = serviceDiscoveryProviderHost;
return this; return this;
} }
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderPort(int serviceDiscoveryProviderPort) public ServiceProviderConfigurationBuilder WithPort(int serviceDiscoveryProviderPort)
{ {
_serviceDiscoveryProviderPort = serviceDiscoveryProviderPort; _serviceDiscoveryProviderPort = serviceDiscoveryProviderPort;
return this; return this;
} }
public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderType(string type) public ServiceProviderConfigurationBuilder WithType(string type)
{ {
_type = type; _type = type;
return this; return this;
} }
public ServiceProviderConfigurationBuilder WithToken(string token)
{
_token = token;
return this;
}
public ServiceProviderConfiguration Build() public ServiceProviderConfiguration Build()
{ {
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort); return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token);
} }
} }
} }

View File

@ -11,9 +11,10 @@ namespace Ocelot.Configuration.Creator
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0; var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
return new ServiceProviderConfigurationBuilder() return new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host) .WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithServiceDiscoveryProviderPort(serviceProviderPort) .WithPort(serviceProviderPort)
.WithServiceDiscoveryProviderType(globalConfiguration?.ServiceDiscoveryProvider?.Type) .WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
.Build(); .Build();
} }
} }

View File

@ -5,5 +5,6 @@ namespace Ocelot.Configuration.File
public string Host {get;set;} public string Host {get;set;}
public int Port { get; set; } public int Port { get; set; }
public string Type { get; set; } public string Type { get; set; }
public string Token { get; set; }
} }
} }

View File

@ -4,8 +4,8 @@ using System.Threading.Tasks;
using Consul; using Consul;
using Newtonsoft.Json; using Newtonsoft.Json;
using Ocelot.Configuration.File; using Ocelot.Configuration.File;
using Ocelot.Infrastructure.Consul;
using Ocelot.Responses; using Ocelot.Responses;
using Ocelot.ServiceDiscovery;
using Ocelot.ServiceDiscovery.Configuration; using Ocelot.ServiceDiscovery.Configuration;
namespace Ocelot.Configuration.Repository namespace Ocelot.Configuration.Repository
@ -13,31 +13,31 @@ namespace Ocelot.Configuration.Repository
public class ConsulFileConfigurationRepository : IFileConfigurationRepository public class ConsulFileConfigurationRepository : IFileConfigurationRepository
{ {
private readonly ConsulClient _consul; private readonly ConsulClient _consul;
private string _ocelotConfiguration = "OcelotConfiguration"; private const string OcelotConfiguration = "OcelotConfiguration";
private readonly Cache.IOcelotCache<FileConfiguration> _cache; private readonly Cache.IOcelotCache<FileConfiguration> _cache;
public ConsulFileConfigurationRepository(Cache.IOcelotCache<FileConfiguration> cache, ServiceProviderConfiguration serviceProviderConfig) public ConsulFileConfigurationRepository(
Cache.IOcelotCache<FileConfiguration> cache,
ServiceProviderConfiguration serviceProviderConfig,
IConsulClientFactory factory)
{ {
var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host; var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host;
var consulPort = serviceProviderConfig?.Port ?? 8500; var consulPort = serviceProviderConfig?.Port ?? 8500;
var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration); var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, serviceProviderConfig?.Token);
_cache = cache; _cache = cache;
_consul = new ConsulClient(c => _consul = factory.Get(config);
{
c.Address = new Uri($"http://{configuration.HostName}:{configuration.Port}");
});
} }
public async Task<Response<FileConfiguration>> Get() public async Task<Response<FileConfiguration>> Get()
{ {
var config = _cache.Get(_ocelotConfiguration, _ocelotConfiguration); var config = _cache.Get(OcelotConfiguration, OcelotConfiguration);
if (config != null) if (config != null)
{ {
return new OkResponse<FileConfiguration>(config); return new OkResponse<FileConfiguration>(config);
} }
var queryResult = await _consul.KV.Get(_ocelotConfiguration); var queryResult = await _consul.KV.Get(OcelotConfiguration);
if (queryResult.Response == null) if (queryResult.Response == null)
{ {
@ -59,7 +59,7 @@ namespace Ocelot.Configuration.Repository
var bytes = Encoding.UTF8.GetBytes(json); var bytes = Encoding.UTF8.GetBytes(json);
var kvPair = new KVPair(_ocelotConfiguration) var kvPair = new KVPair(OcelotConfiguration)
{ {
Value = bytes Value = bytes
}; };
@ -68,7 +68,7 @@ namespace Ocelot.Configuration.Repository
if (result.Response) if (result.Response)
{ {
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), _ocelotConfiguration); _cache.AddAndDelete(OcelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), OcelotConfiguration);
return new OkResponse(); return new OkResponse();
} }

View File

@ -2,15 +2,17 @@
{ {
public class ServiceProviderConfiguration public class ServiceProviderConfiguration
{ {
public ServiceProviderConfiguration(string type, string host, int port) public ServiceProviderConfiguration(string type, string host, int port, string token)
{ {
Host = host; Host = host;
Port = port; Port = port;
Token = token;
Type = type; Type = type;
} }
public string Host { get; private set; } public string Host { get; }
public int Port { get; private set; } public int Port { get; }
public string Type { get; private set; } public string Type { get; }
public string Token { get; }
} }
} }

View File

@ -53,6 +53,7 @@ namespace Ocelot.DependencyInjection
using System.Net.Http; using System.Net.Http;
using Butterfly.Client.AspNetCore; using Butterfly.Client.AspNetCore;
using Ocelot.Infrastructure; using Ocelot.Infrastructure;
using Ocelot.Infrastructure.Consul;
public class OcelotBuilder : IOcelotBuilder public class OcelotBuilder : IOcelotBuilder
{ {
@ -152,6 +153,7 @@ namespace Ocelot.DependencyInjection
_services.TryAddSingleton<IConsulPollerConfiguration, InMemoryConsulPollerConfiguration>(); _services.TryAddSingleton<IConsulPollerConfiguration, InMemoryConsulPollerConfiguration>();
_services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>(); _services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
_services.TryAddSingleton<IPlaceholders, Placeholders>(); _services.TryAddSingleton<IPlaceholders, Placeholders>();
_services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
} }
public IOcelotAdministrationBuilder AddAdministration(string path, string secret) public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
@ -236,10 +238,12 @@ namespace Ocelot.DependencyInjection
{ {
var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0); var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0);
var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty); var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty);
var serviceDiscoveryToken = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Token", string.Empty);
var config = new ServiceProviderConfigurationBuilder() var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderPort(serviceDiscoveryPort) .WithPort(serviceDiscoveryPort)
.WithServiceDiscoveryProviderHost(serviceDiscoveryHost) .WithHost(serviceDiscoveryHost)
.WithToken(serviceDiscoveryToken)
.Build(); .Build();
_services.AddSingleton<ServiceProviderConfiguration>(config); _services.AddSingleton<ServiceProviderConfiguration>(config);

View File

@ -0,0 +1,22 @@
using System;
using Consul;
using Ocelot.ServiceDiscovery.Configuration;
namespace Ocelot.Infrastructure.Consul
{
public class ConsulClientFactory : IConsulClientFactory
{
public ConsulClient Get(ConsulRegistryConfiguration config)
{
return new ConsulClient(c =>
{
c.Address = new Uri($"http://{config.Host}:{config.Port}");
if (!string.IsNullOrEmpty(config?.Token))
{
c.Token = config.Token;
}
});
}
}
}

View File

@ -0,0 +1,10 @@
using Consul;
using Ocelot.ServiceDiscovery.Configuration;
namespace Ocelot.Infrastructure.Consul
{
public interface IConsulClientFactory
{
ConsulClient Get(ConsulRegistryConfiguration config);
}
}

View File

@ -26,27 +26,27 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
<PackageReference Include="FluentValidation" Version="7.2.1" /> <PackageReference Include="FluentValidation" Version="7.5.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" /> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" /> <PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
<PackageReference Include="CacheManager.Core" Version="1.1.1" /> <PackageReference Include="CacheManager.Core" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.1" /> <PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.1" /> <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Consul" Version="0.7.2.3" /> <PackageReference Include="Consul" Version="0.7.2.4" />
<PackageReference Include="Polly" Version="5.3.1" /> <PackageReference Include="Polly" Version="5.8.0" />
<PackageReference Include="IdentityServer4" Version="2.0.2" /> <PackageReference Include="IdentityServer4" Version="2.1.3" />
<PackageReference Include="Rafty" Version="0.4.2" /> <PackageReference Include="Rafty" Version="0.4.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,15 +2,17 @@ namespace Ocelot.ServiceDiscovery.Configuration
{ {
public class ConsulRegistryConfiguration public class ConsulRegistryConfiguration
{ {
public ConsulRegistryConfiguration(string hostName, int port, string keyOfServiceInConsul) public ConsulRegistryConfiguration(string host, int port, string keyOfServiceInConsul, string token)
{ {
HostName = hostName; Host = host;
Port = port; Port = port;
KeyOfServiceInConsul = keyOfServiceInConsul; KeyOfServiceInConsul = keyOfServiceInConsul;
Token = token;
} }
public string KeyOfServiceInConsul { get; private set; } public string KeyOfServiceInConsul { get; }
public string HostName { get; private set; } public string Host { get; }
public int Port { get; private set; } public int Port { get; }
public string Token { get; }
} }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Consul; using Consul;
using Ocelot.Infrastructure.Consul;
using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration; using Ocelot.ServiceDiscovery.Configuration;
@ -12,30 +13,27 @@ namespace Ocelot.ServiceDiscovery.Providers
{ {
public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
{ {
private readonly ConsulRegistryConfiguration _consulConfig; private readonly ConsulRegistryConfiguration _config;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
private readonly ConsulClient _consul; private readonly ConsulClient _consul;
private const string VersionPrefix = "version-"; private const string VersionPrefix = "version-";
public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration, IOcelotLoggerFactory factory) public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
{; {;
_logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>(); _logger = factory.CreateLogger<ConsulServiceDiscoveryProvider>();
var consulHost = string.IsNullOrEmpty(consulRegistryConfiguration?.HostName) ? "localhost" : consulRegistryConfiguration.HostName; var consulHost = string.IsNullOrEmpty(config?.Host) ? "localhost" : config.Host;
var consulPort = consulRegistryConfiguration?.Port ?? 8500; var consulPort = config?.Port ?? 8500;
_consulConfig = new ConsulRegistryConfiguration(consulHost, consulPort, consulRegistryConfiguration?.KeyOfServiceInConsul); _config = new ConsulRegistryConfiguration(consulHost, consulPort, config?.KeyOfServiceInConsul, config?.Token);
_consul = new ConsulClient(config => _consul = clientFactory.Get(_config);
{
config.Address = new Uri($"http://{_consulConfig.HostName}:{_consulConfig.Port}");
});
} }
public async Task<List<Service>> Get() public async Task<List<Service>> Get()
{ {
var queryResult = await _consul.Health.Service(_consulConfig.KeyOfServiceInConsul, string.Empty, true); var queryResult = await _consul.Health.Service(_config.KeyOfServiceInConsul, string.Empty, true);
var services = new List<Service>(); var services = new List<Service>();

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration; using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers; using Ocelot.ServiceDiscovery.Providers;
@ -10,10 +11,12 @@ namespace Ocelot.ServiceDiscovery
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
{ {
private readonly IOcelotLoggerFactory _factory; private readonly IOcelotLoggerFactory _factory;
private readonly IConsulClientFactory _clientFactory;
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory) public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
{ {
_factory = factory; _factory = factory;
_clientFactory = clientFactory;
} }
public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute) public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
@ -43,8 +46,8 @@ namespace Ocelot.ServiceDiscovery
return new ServiceFabricServiceDiscoveryProvider(config); return new ServiceFabricServiceDiscoveryProvider(config);
} }
var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName); var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName, serviceConfig.Token);
return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory); return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory, _clientFactory);
} }
} }
} }

View File

@ -104,7 +104,7 @@ namespace Ocelot.AcceptanceTests
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom")) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
.BDDfy(); .BDDfy();
var commandOnAllStateMachines = WaitFor(5000).Until(() => _butterflyCalled == 4); var commandOnAllStateMachines = WaitFor(10000).Until(() => _butterflyCalled == 4);
commandOnAllStateMachines.ShouldBeTrue(); commandOnAllStateMachines.ShouldBeTrue();
} }

View File

@ -16,7 +16,6 @@ namespace Ocelot.AcceptanceTests
public class HeaderTests : IDisposable public class HeaderTests : IDisposable
{ {
private IWebHost _builder; private IWebHost _builder;
private string _cookieValue;
private int _count; private int _count;
private readonly Steps _steps; private readonly Steps _steps;
@ -278,26 +277,27 @@ namespace Ocelot.AcceptanceTests
.Configure(app => .Configure(app =>
{ {
app.UsePathBase(basePath); app.UsePathBase(basePath);
app.Run(async context => app.Run(context =>
{ {
if(_count == 0) if (_count == 0)
{ {
context.Response.Cookies.Append("test", "0"); context.Response.Cookies.Append("test", "0");
_count++; _count++;
context.Response.StatusCode = statusCode; context.Response.StatusCode = statusCode;
return; return Task.CompletedTask;
} }
if(context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue)) if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
{ {
if(cookieValue == "0" || headerValue == "test=1; path=/") if (cookieValue == "0" || headerValue == "test=1; path=/")
{ {
context.Response.StatusCode = statusCode; context.Response.StatusCode = statusCode;
return; return Task.CompletedTask;
} }
} }
context.Response.StatusCode = 500; context.Response.StatusCode = 500;
return Task.CompletedTask;
}); });
}) })
.Build(); .Build();

View File

@ -27,26 +27,26 @@
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CacheManager.Serialization.Json" Version="1.1.1" /> <PackageReference Include="CacheManager.Serialization.Json" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.0.1" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
<PackageReference Include="Shouldly" Version="3.0.0-beta0003" /> <PackageReference Include="Shouldly" Version="3.0.0" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="Consul" Version="0.7.2.3" /> <PackageReference Include="Consul" Version="0.7.2.4" />
<PackageReference Include="xunit" Version="2.3.1" /> <PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
</ItemGroup> </ItemGroup>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using Consul; using Consul;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@ -22,9 +23,10 @@ namespace Ocelot.AcceptanceTests
private readonly List<ServiceEntry> _serviceEntries; private readonly List<ServiceEntry> _serviceEntries;
private int _counterOne; private int _counterOne;
private int _counterTwo; private int _counterTwo;
private static readonly object _syncLock = new object(); private static readonly object SyncLock = new object();
private IWebHost _builder; private IWebHost _builder;
private string _downstreamPath; private string _downstreamPath;
private string _receivedToken;
public ServiceDiscoveryTests() public ServiceDiscoveryTests()
{ {
@ -100,13 +102,13 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
//test from issue 213 //test from issue #213
[Fact] [Fact]
public void should_handle_request_to_consul_for_downstream_service_and_make_request() public void should_handle_request_to_consul_for_downstream_service_and_make_request()
{ {
var consulPort = 8505; const int consulPort = 8505;
var serviceName = "web"; const string serviceName = "web";
var downstreamServiceOneUrl = "http://localhost:8080"; const string downstreamServiceOneUrl = "http://localhost:8080";
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}"; var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
var serviceEntryOne = new ServiceEntry() var serviceEntryOne = new ServiceEntry()
{ {
@ -116,7 +118,7 @@ namespace Ocelot.AcceptanceTests
Address = "localhost", Address = "localhost",
Port = 8080, Port = 8080,
ID = "web_90_0_2_224_8080", ID = "web_90_0_2_224_8080",
Tags = new string[1]{"version-v1"} Tags = new[] {"version-v1"}
}, },
}; };
@ -145,14 +147,73 @@ namespace Ocelot.AcceptanceTests
} }
}; };
this.Given(x => x.GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura")) this.Given(x => x.GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura"))
.And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName)) .And(x => x.GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
.And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne)) .And(x => x.GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/home")) .When(x => _steps.WhenIGetUrlOnTheApiGateway("/home"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
//test from issue #295
[Fact]
public void should_use_token_to_make_request_to_consul()
{
var token = "abctoken";
var consulPort = 8515;
var serviceName = "web";
var downstreamServiceOneUrl = "http://localhost:8081";
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = serviceName,
Address = "localhost",
Port = 8081,
ID = "web_90_0_2_224_8080",
Tags = new[] { "version-v1" }
},
};
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/api/home",
DownstreamScheme = "http",
UpstreamPathTemplate = "/home",
UpstreamHttpMethod = new List<string> { "Get", "Options" },
ServiceName = serviceName,
LoadBalancer = "LeastConnection",
UseServiceDiscovery = true,
}
},
GlobalConfiguration = new FileGlobalConfiguration()
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
{
Host = "localhost",
Port = consulPort,
Token = token
}
}
};
this.Given(_ => GivenThereIsAServiceRunningOn(downstreamServiceOneUrl, "/api/home", 200, "Hello from Laura"))
.And(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, serviceName))
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
.And(_ => _steps.GivenThereIsAConfiguration(configuration))
.And(_ => _steps.GivenOcelotIsRunning())
.When(_ => _steps.WhenIGetUrlOnTheApiGateway("/home"))
.Then(_ => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(_ => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.And(_ => _receivedToken.ShouldBe(token))
.BDDfy(); .BDDfy();
} }
@ -289,6 +350,11 @@ namespace Ocelot.AcceptanceTests
{ {
if(context.Request.Path.Value == $"/v1/health/service/{serviceName}") if(context.Request.Path.Value == $"/v1/health/service/{serviceName}")
{ {
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
{
_receivedToken = values.First();
}
await context.Response.WriteJsonAsync(_serviceEntries); await context.Response.WriteJsonAsync(_serviceEntries);
} }
}); });
@ -312,8 +378,8 @@ namespace Ocelot.AcceptanceTests
{ {
try try
{ {
var response = string.Empty; string response;
lock (_syncLock) lock (SyncLock)
{ {
_counterOne++; _counterOne++;
response = _counterOne.ToString(); response = _counterOne.ToString();
@ -321,7 +387,7 @@ namespace Ocelot.AcceptanceTests
context.Response.StatusCode = statusCode; context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(response); await context.Response.WriteAsync(response);
} }
catch (System.Exception exception) catch (Exception exception)
{ {
await context.Response.WriteAsync(exception.StackTrace); await context.Response.WriteAsync(exception.StackTrace);
} }
@ -346,8 +412,8 @@ namespace Ocelot.AcceptanceTests
{ {
try try
{ {
var response = string.Empty; string response;
lock (_syncLock) lock (SyncLock)
{ {
_counterTwo++; _counterTwo++;
response = _counterTwo.ToString(); response = _counterTwo.ToString();
@ -356,7 +422,7 @@ namespace Ocelot.AcceptanceTests
context.Response.StatusCode = statusCode; context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(response); await context.Response.WriteAsync(response);
} }
catch (System.Exception exception) catch (Exception exception)
{ {
await context.Response.WriteAsync(exception.StackTrace); await context.Response.WriteAsync(exception.StackTrace);
} }

View File

@ -1,722 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using CacheManager.Core;
using IdentityServer4.AccessTokenValidation;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Shouldly;
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
using Ocelot.AcceptanceTests.Caching;
<<<<<<< HEAD
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
||||||| merged common ancestors
=======
using System.IO.Compression;
using System.Text;
>>>>>>> develop
namespace Ocelot.AcceptanceTests
{
public class Steps : IDisposable
{
private TestServer _ocelotServer;
private HttpClient _ocelotClient;
private HttpResponseMessage _response;
private HttpContent _postContent;
private BearerToken _token;
public HttpClient OcelotClient => _ocelotClient;
public string RequestIdKey = "OcRequestId";
private readonly Random _random;
private IWebHostBuilder _webHostBuilder;
public Steps()
{
_random = new Random();
}
public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
{
var configurationPath = TestConfiguration.ConfigurationPath;
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
if (File.Exists(configurationPath))
{
File.Delete(configurationPath);
}
File.WriteAllText(configurationPath, jsonConfiguration);
}
public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration, string configurationPath)
{
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
if (File.Exists(configurationPath))
{
File.Delete(configurationPath);
}
File.WriteAllText(configurationPath, jsonConfiguration);
}
/// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary>
public void GivenOcelotIsRunning()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot();
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
internal void GivenOcelotIsRunningUsingButterfly(string butterflyUrl)
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddOpenTracing(option =>
{
//this is the url that the butterfly collector server is running on...
option.CollectorUrl = butterflyUrl;
option.Service = "Ocelot";
});
})
.Configure(app =>
{
app.Use(async (context, next) =>
{
await next.Invoke();
});
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
/*
public void GivenIHaveAddedXForwardedForHeader(string value)
{
_ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Forwarded-For", value);
}*/
public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback)
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot();
})
.Configure(app =>
{
app.UseMiddleware<T>(callback);
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>()
where TOne : DelegatingHandler
where TWo : DelegatingHandler
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
s.AddOcelot()
.AddDelegatingHandler<TOne>()
.AddDelegatingHandler<TWo>();
})
.Configure(a =>
{
a.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency)
where TOne : DelegatingHandler
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
s.AddSingleton<FakeDependency>(dependency);
s.AddOcelot()
.AddDelegatingHandler<TOne>();
})
.Configure(a =>
{
a.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
/// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary>
public void GivenOcelotIsRunning(Action<IdentityServerAuthenticationOptions> options, string authenticationProviderKey)
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot();
s.AddAuthentication()
.AddIdentityServerAuthentication(authenticationProviderKey, options);
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void ThenTheResponseHeaderIs(string key, string value)
{
var header = _response.Headers.GetValues(key);
header.First().ShouldBe(value);
}
public void GivenOcelotIsRunningUsingJsonSerializedCache()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddCacheManager((x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithJsonSerializer()
.WithHandle(typeof(InMemoryJsonHandle<>));
});
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningUsingConsulToStoreConfig()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot().AddStoreOcelotConfigurationInConsul();
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache()
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
config.AddJsonFile("configuration.json");
config.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot()
.AddCacheManager((x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithJsonSerializer()
.WithHandle(typeof(InMemoryJsonHandle<>));
})
.AddStoreOcelotConfigurationInConsul();
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
_ocelotServer = new TestServer(_webHostBuilder);
_ocelotClient = _ocelotServer.CreateClient();
}
internal void ThenTheResponseShouldBe(FileConfiguration expecteds)
{
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
response.GlobalConfiguration.RequestIdKey.ShouldBe(expecteds.GlobalConfiguration.RequestIdKey);
response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Host);
response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Port);
for (var i = 0; i < response.ReRoutes.Count; i++)
{
for (var j = 0; j < response.ReRoutes[i].DownstreamHostAndPorts.Count; j++)
{
var result = response.ReRoutes[i].DownstreamHostAndPorts[j];
var expected = expecteds.ReRoutes[i].DownstreamHostAndPorts[j];
result.Host.ShouldBe(expected.Host);
result.Port.ShouldBe(expected.Port);
}
response.ReRoutes[i].DownstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].DownstreamPathTemplate);
response.ReRoutes[i].DownstreamScheme.ShouldBe(expecteds.ReRoutes[i].DownstreamScheme);
response.ReRoutes[i].UpstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].UpstreamPathTemplate);
response.ReRoutes[i].UpstreamHttpMethod.ShouldBe(expecteds.ReRoutes[i].UpstreamHttpMethod);
}
}
/// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary>
public void GivenOcelotIsRunning(OcelotPipelineConfiguration ocelotPipelineConfig)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("configuration.json")
.AddEnvironmentVariables();
var configuration = builder.Build();
_webHostBuilder = new WebHostBuilder();
_webHostBuilder.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
});
_ocelotServer = new TestServer(_webHostBuilder
.UseConfiguration(configuration)
.ConfigureServices(s =>
{
Action<ConfigurationBuilderCachePart> settings = (x) =>
{
x.WithMicrosoftLogging(log =>
{
log.AddConsole(LogLevel.Debug);
})
.WithDictionaryHandle();
};
s.AddOcelot(configuration);
})
.ConfigureLogging(l =>
{
l.AddConsole();
l.AddDebug();
})
.Configure(a =>
{
a.UseOcelot(ocelotPipelineConfig).Wait();
}));
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenIHaveAddedATokenToMyRequest()
{
_ocelotClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
}
public void GivenIHaveAToken(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveATokenForApiReadOnlyScope(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api.readOnly"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveATokenForApi2(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api2"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveAnOcelotToken(string adminPath)
{
var tokenUrl = $"{adminPath}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "admin"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "admin"),
new KeyValuePair<string, string>("username", "admin"),
new KeyValuePair<string, string>("password", "admin"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
var response = _ocelotClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
public void VerifyIdentiryServerStarted(string url)
{
using (var httpClient = new HttpClient())
{
var response = httpClient.GetAsync($"{url}/.well-known/openid-configuration").Result;
response.EnsureSuccessStatusCode();
}
}
public void WhenIGetUrlOnTheApiGateway(string url)
{
_response = _ocelotClient.GetAsync(url).Result;
}
public void GivenIAddAHeader(string key, string value)
{
_ocelotClient.DefaultRequestHeaders.Add(key, value);
}
public void WhenIGetUrlOnTheApiGatewayMultipleTimes(string url, int times)
{
var tasks = new Task[times];
for (int i = 0; i < times; i++)
{
var urlCopy = url;
tasks[i] = GetForServiceDiscoveryTest(urlCopy);
Thread.Sleep(_random.Next(40, 60));
}
Task.WaitAll(tasks);
}
private async Task GetForServiceDiscoveryTest(string url)
{
var response = await _ocelotClient.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
int count = int.Parse(content);
count.ShouldBeGreaterThan(0);
}
public void WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit(string url, int times)
{
for (int i = 0; i < times; i++)
{
var clientId = "ocelotclient1";
var request = new HttpRequestMessage(new HttpMethod("GET"), url);
request.Headers.Add("ClientId", clientId);
_response = _ocelotClient.SendAsync(request).Result;
}
}
public void WhenIGetUrlOnTheApiGateway(string url, string requestId)
{
_ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation(RequestIdKey, requestId);
_response = _ocelotClient.GetAsync(url).Result;
}
public void WhenIPostUrlOnTheApiGateway(string url)
{
_response = _ocelotClient.PostAsync(url, _postContent).Result;
}
public void GivenThePostHasContent(string postcontent)
{
_postContent = new StringContent(postcontent);
}
public void GivenThePostHasGzipContent(object input)
{
string json = JsonConvert.SerializeObject(input);
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
MemoryStream ms = new MemoryStream();
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
{
gzip.Write(jsonBytes, 0, jsonBytes.Length);
}
ms.Position = 0;
StreamContent content = new StreamContent(ms);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentEncoding.Add("gzip");
_postContent = content;
}
public void ThenTheResponseBodyShouldBe(string expectedBody)
{
_response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody);
}
public void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
{
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
}
public void ThenTheStatusCodeShouldBe(int expectedHttpStatusCode)
{
var responseStatusCode = (int)_response.StatusCode;
responseStatusCode.ShouldBe(expectedHttpStatusCode);
}
public void Dispose()
{
_ocelotClient?.Dispose();
_ocelotServer?.Dispose();
}
public void ThenTheRequestIdIsReturned()
{
_response.Headers.GetValues(RequestIdKey).First().ShouldNotBeNullOrEmpty();
}
public void ThenTheRequestIdIsReturned(string expected)
{
_response.Headers.GetValues(RequestIdKey).First().ShouldBe(expected);
}
public void ThenTheContentLengthIs(int expected)
{
_response.Content.Headers.ContentLength.ShouldBe(expected);
}
public void WhenIMakeLotsOfDifferentRequestsToTheApiGateway()
{
int numberOfRequests = 100;
var aggregateUrl = "/";
var aggregateExpected = "{\"Laura\":{Hello from Laura},\"Tom\":{Hello from Tom}}";
var tomUrl = "/tom";
var tomExpected = "{Hello from Tom}";
var lauraUrl = "/laura";
var lauraExpected = "{Hello from Laura}";
var random = new Random();
var aggregateTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
aggregateTasks[i] = Fire(aggregateUrl, aggregateExpected, random);
}
var tomTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
tomTasks[i] = Fire(tomUrl, tomExpected, random);
}
var lauraTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
lauraTasks[i] = Fire(lauraUrl, lauraExpected, random);
}
Task.WaitAll(lauraTasks);
Task.WaitAll(tomTasks);
Task.WaitAll(aggregateTasks);
}
private async Task Fire(string url, string expectedBody, Random random)
{
var request = new HttpRequestMessage(new HttpMethod("GET"), url);
await Task.Delay(random.Next(0, 2));
var response = await _ocelotClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
content.ShouldBe(expectedBody);
}
}
}

View File

@ -37,7 +37,7 @@ namespace Ocelot.AcceptanceTests
} }
[Fact] [Fact]
public async Task should_proxy_websocket_input_to_downstream_service() public void should_proxy_websocket_input_to_downstream_service()
{ {
var downstreamPort = 5001; var downstreamPort = 5001;
var downstreamHost = "localhost"; var downstreamHost = "localhost";
@ -72,7 +72,7 @@ namespace Ocelot.AcceptanceTests
} }
[Fact] [Fact]
public async Task should_proxy_websocket_input_to_downstream_service_and_use_load_balancer() public void should_proxy_websocket_input_to_downstream_service_and_use_load_balancer()
{ {
var downstreamPort = 5005; var downstreamPort = 5005;
var downstreamHost = "localhost"; var downstreamHost = "localhost";
@ -116,7 +116,7 @@ namespace Ocelot.AcceptanceTests
} }
[Fact] [Fact]
public async Task should_proxy_websocket_input_to_downstream_service_and_use_service_discovery_and_load_balancer() public void should_proxy_websocket_input_to_downstream_service_and_use_service_discovery_and_load_balancer()
{ {
var downstreamPort = 5007; var downstreamPort = 5007;
var downstreamHost = "localhost"; var downstreamHost = "localhost";
@ -274,7 +274,6 @@ namespace Ocelot.AcceptanceTests
{ {
_firstRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count)); _firstRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count));
} }
else if (result.MessageType == WebSocketMessageType.Close) else if (result.MessageType == WebSocketMessageType.Close)
{ {
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
@ -321,7 +320,6 @@ namespace Ocelot.AcceptanceTests
{ {
_secondRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count)); _secondRecieved.Add(Encoding.UTF8.GetString(buffer, 0, result.Count));
} }
else if (result.MessageType == WebSocketMessageType.Close) else if (result.MessageType == WebSocketMessageType.Close)
{ {
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
@ -333,7 +331,6 @@ namespace Ocelot.AcceptanceTests
await Task.WhenAll(sending, receiving); await Task.WhenAll(sending, receiving);
} }
private async Task StartFakeDownstreamService(string url, string path) private async Task StartFakeDownstreamService(string url, string path)
{ {
_firstDownstreamHost = new WebHostBuilder() _firstDownstreamHost = new WebHostBuilder()
@ -380,7 +377,6 @@ namespace Ocelot.AcceptanceTests
await _firstDownstreamHost.StartAsync(); await _firstDownstreamHost.StartAsync();
} }
private async Task StartSecondFakeDownstreamService(string url, string path) private async Task StartSecondFakeDownstreamService(string url, string path)
{ {
_secondDownstreamHost = new WebHostBuilder() _secondDownstreamHost = new WebHostBuilder()
@ -427,7 +423,6 @@ namespace Ocelot.AcceptanceTests
await _secondDownstreamHost.StartAsync(); await _secondDownstreamHost.StartAsync();
} }
private async Task Echo(WebSocket webSocket) private async Task Echo(WebSocket webSocket)
{ {
try try

View File

@ -19,7 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.12" /> <PackageReference Include="BenchmarkDotNet" Version="0.10.13" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>

View File

@ -25,26 +25,26 @@
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" /> <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
<PackageReference Include="xunit" Version="2.3.1" /> <PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="IdentityServer4" Version="2.0.2" /> <PackageReference Include="IdentityServer4" Version="2.1.3" />
<PackageReference Include="Shouldly" Version="3.0.0-beta0003" /> <PackageReference Include="Shouldly" Version="3.0.0" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="Consul" Version="0.7.2.3" /> <PackageReference Include="Consul" Version="0.7.2.4" />
<PackageReference Include="Rafty" Version="0.4.2" /> <PackageReference Include="Rafty" Version="0.4.2" />
<PackageReference Include="Microsoft.Data.SQLite" Version="2.0.0" /> <PackageReference Include="Microsoft.Data.SQLite" Version="2.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -21,19 +21,19 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj"/> <ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0"/> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0"/> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="Consul" Version="0.7.2.3"/> <PackageReference Include="Consul" Version="0.7.2.4" />
<PackageReference Include="Polly" Version="5.3.1"/> <PackageReference Include="Polly" Version="5.8.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>

View File

@ -10,8 +10,7 @@ namespace Ocelot.UnitTests.Configuration
{ {
public class ServiceProviderCreatorTests public class ServiceProviderCreatorTests
{ {
private ServiceProviderConfigurationCreator _creator; private readonly ServiceProviderConfigurationCreator _creator;
private FileReRoute _reRoute;
private FileGlobalConfiguration _globalConfig; private FileGlobalConfiguration _globalConfig;
private ServiceProviderConfiguration _result; private ServiceProviderConfiguration _result;
@ -23,36 +22,30 @@ namespace Ocelot.UnitTests.Configuration
[Fact] [Fact]
public void should_create_service_provider_config() public void should_create_service_provider_config()
{ {
var reRoute = new FileReRoute();
var globalConfig = new FileGlobalConfiguration var globalConfig = new FileGlobalConfiguration
{ {
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
Port = 1234, Port = 1234,
Type = "ServiceFabric" Type = "ServiceFabric",
Token = "testtoken"
} }
}; };
var expected = new ServiceProviderConfigurationBuilder() var expected = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderHost("127.0.0.1") .WithHost("127.0.0.1")
.WithServiceDiscoveryProviderPort(1234) .WithPort(1234)
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.WithToken("testtoken")
.Build(); .Build();
this.Given(x => x.GivenTheFollowingReRoute(reRoute)) this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig))
.And(x => x.GivenTheFollowingGlobalConfig(globalConfig))
.When(x => x.WhenICreate()) .When(x => x.WhenICreate())
.Then(x => x.ThenTheConfigIs(expected)) .Then(x => x.ThenTheConfigIs(expected))
.BDDfy(); .BDDfy();
} }
private void GivenTheFollowingReRoute(FileReRoute fileReRoute)
{
_reRoute = fileReRoute;
}
private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration fileGlobalConfig) private void GivenTheFollowingGlobalConfig(FileGlobalConfiguration fileGlobalConfig)
{ {
_globalConfig = fileGlobalConfig; _globalConfig = fileGlobalConfig;
@ -67,6 +60,8 @@ namespace Ocelot.UnitTests.Configuration
{ {
_result.Host.ShouldBe(expected.Host); _result.Host.ShouldBe(expected.Host);
_result.Port.ShouldBe(expected.Port); _result.Port.ShouldBe(expected.Port);
_result.Token.ShouldBe(expected.Token);
_result.Type.ShouldBe(expected.Type);
} }
} }
} }

View File

@ -82,9 +82,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.Build(); .Build();
var config = new ServiceProviderConfigurationBuilder() var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.WithServiceDiscoveryProviderHost("localhost") .WithHost("localhost")
.WithServiceDiscoveryProviderPort(19081) .WithPort(19081)
.Build(); .Build();
this.Given(x => x.GivenTheDownStreamRouteIs( this.Given(x => x.GivenTheDownStreamRouteIs(
@ -118,9 +118,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.Build()); .Build());
var config = new ServiceProviderConfigurationBuilder() var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.WithServiceDiscoveryProviderHost("localhost") .WithHost("localhost")
.WithServiceDiscoveryProviderPort(19081) .WithPort(19081)
.Build(); .Build();
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
@ -148,9 +148,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.Build()); .Build());
var config = new ServiceProviderConfigurationBuilder() var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.WithServiceDiscoveryProviderHost("localhost") .WithHost("localhost")
.WithServiceDiscoveryProviderPort(19081) .WithPort(19081)
.Build(); .Build();
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
@ -178,9 +178,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
.Build()); .Build());
var config = new ServiceProviderConfigurationBuilder() var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.WithServiceDiscoveryProviderHost("localhost") .WithHost("localhost")
.WithServiceDiscoveryProviderPort(19081) .WithPort(19081)
.Build(); .Build();
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))

View File

@ -25,7 +25,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{ {
_factory = new Mock<ILoadBalancerFactory>(); _factory = new Mock<ILoadBalancerFactory>();
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object); _loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
_serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123); _serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123, string.Empty);
} }
[Fact] [Fact]

View File

@ -35,23 +35,23 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.0" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20171031-01" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2"> <PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" /> <PackageReference Include="Microsoft.DotNet.InternalAbstractions" Version="1.0.500-preview2-1-003177" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="Moq" Version="4.7.142" /> <PackageReference Include="Moq" Version="4.8.2" />
<PackageReference Include="Shouldly" Version="3.0.0-beta0003" /> <PackageReference Include="Shouldly" Version="3.0.0" />
<PackageReference Include="TestStack.BDDfy" Version="4.3.2" /> <PackageReference Include="TestStack.BDDfy" Version="4.3.2" />
<PackageReference Include="xunit" Version="2.3.1" /> <PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" /> <PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />

View File

@ -1,14 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Linq;
using Consul; using Consul;
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 Moq; using Moq;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.ServiceDiscovery;
using Ocelot.ServiceDiscovery.Configuration; using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers; using Ocelot.ServiceDiscovery.Providers;
using Ocelot.Values; using Ocelot.Values;
@ -22,14 +22,16 @@ namespace Ocelot.UnitTests.ServiceDiscovery
{ {
private IWebHost _fakeConsulBuilder; private IWebHost _fakeConsulBuilder;
private readonly List<ServiceEntry> _serviceEntries; private readonly List<ServiceEntry> _serviceEntries;
private readonly ConsulServiceDiscoveryProvider _provider; private ConsulServiceDiscoveryProvider _provider;
private readonly string _serviceName; private readonly string _serviceName;
private readonly int _port; private readonly int _port;
private readonly string _consulHost; private readonly string _consulHost;
private readonly string _fakeConsulServiceDiscoveryUrl; private readonly string _fakeConsulServiceDiscoveryUrl;
private List<Service> _services; private List<Service> _services;
private Mock<IOcelotLoggerFactory> _factory; private readonly Mock<IOcelotLoggerFactory> _factory;
private readonly Mock<IOcelotLogger> _logger; private readonly Mock<IOcelotLogger> _logger;
private string _receivedToken;
private IConsulClientFactory _clientFactory;
public ConsulServiceDiscoveryProviderTests() public ConsulServiceDiscoveryProviderTests()
{ {
@ -40,11 +42,12 @@ namespace Ocelot.UnitTests.ServiceDiscovery
_serviceEntries = new List<ServiceEntry>(); _serviceEntries = new List<ServiceEntry>();
_factory = new Mock<IOcelotLoggerFactory>(); _factory = new Mock<IOcelotLoggerFactory>();
_clientFactory = new ConsulClientFactory();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_factory.Setup(x => x.CreateLogger<ConsulServiceDiscoveryProvider>()).Returns(_logger.Object); _factory.Setup(x => x.CreateLogger<ConsulServiceDiscoveryProvider>()).Returns(_logger.Object);
var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName); var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName, null);
_provider = new ConsulServiceDiscoveryProvider(config, _factory.Object); _provider = new ConsulServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
} }
[Fact] [Fact]
@ -69,6 +72,33 @@ namespace Ocelot.UnitTests.ServiceDiscovery
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_use_token()
{
var token = "test token";
var config = new ConsulRegistryConfiguration(_consulHost, _port, _serviceName, token);
_provider = new ConsulServiceDiscoveryProvider(config, _factory.Object, _clientFactory);
var serviceEntryOne = new ServiceEntry()
{
Service = new AgentService()
{
Service = _serviceName,
Address = "localhost",
Port = 50881,
ID = Guid.NewGuid().ToString(),
Tags = new string[0]
},
};
this.Given(_ => GivenThereIsAFakeConsulServiceDiscoveryProvider(_fakeConsulServiceDiscoveryUrl, _serviceName))
.And(_ => GivenTheServicesAreRegisteredWithConsul(serviceEntryOne))
.When(_ => WhenIGetTheServices())
.Then(_ => ThenTheCountIs(1))
.And(_ => _receivedToken.ShouldBe(token))
.BDDfy();
}
[Fact] [Fact]
public void should_not_return_services_with_invalid_address() public void should_not_return_services_with_invalid_address()
{ {
@ -197,6 +227,11 @@ namespace Ocelot.UnitTests.ServiceDiscovery
{ {
if (context.Request.Path.Value == $"/v1/health/service/{serviceName}") if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
{ {
if (context.Request.Headers.TryGetValue("X-Consul-Token", out var values))
{
_receivedToken = values.First();
}
await context.Response.WriteJsonAsync(_serviceEntries); await context.Response.WriteJsonAsync(_serviceEntries);
} }
}); });

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.ServiceDiscovery; using Ocelot.ServiceDiscovery;
using Ocelot.ServiceDiscovery.Providers; using Ocelot.ServiceDiscovery.Providers;
@ -19,11 +20,13 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private readonly ServiceDiscoveryProviderFactory _factory; private readonly ServiceDiscoveryProviderFactory _factory;
private DownstreamReRoute _reRoute; private DownstreamReRoute _reRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private IConsulClientFactory _clientFactory;
public ServiceProviderFactoryTests() public ServiceProviderFactoryTests()
{ {
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
_factory = new ServiceDiscoveryProviderFactory(_loggerFactory.Object); _clientFactory = new ConsulClientFactory();
_factory = new ServiceDiscoveryProviderFactory(_loggerFactory.Object, _clientFactory);
} }
[Fact] [Fact]
@ -87,7 +90,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
.Build(); .Build();
var serviceConfig = new ServiceProviderConfigurationBuilder() var serviceConfig = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderType("ServiceFabric") .WithType("ServiceFabric")
.Build(); .Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute)) this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))