Skip to content

Commit

Permalink
Feature/#295 consul acl (#307)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
TomPallister authored Apr 8, 2018
1 parent d7ef956 commit 982eebf
Show file tree
Hide file tree
Showing 28 changed files with 345 additions and 908 deletions.
15 changes: 15 additions & 0 deletions docs/features/servicediscovery.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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.
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,35 @@ public class ServiceProviderConfigurationBuilder
private string _serviceDiscoveryProviderHost;
private int _serviceDiscoveryProviderPort;
private string _type;
private string _token;

public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderHost(string serviceDiscoveryProviderHost)
public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost)
{
_serviceDiscoveryProviderHost = serviceDiscoveryProviderHost;
return this;
}

public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderPort(int serviceDiscoveryProviderPort)
public ServiceProviderConfigurationBuilder WithPort(int serviceDiscoveryProviderPort)
{
_serviceDiscoveryProviderPort = serviceDiscoveryProviderPort;
return this;
}

public ServiceProviderConfigurationBuilder WithServiceDiscoveryProviderType(string type)
public ServiceProviderConfigurationBuilder WithType(string type)
{
_type = type;
return this;
}

public ServiceProviderConfigurationBuilder WithToken(string token)
{
_token = token;
return this;
}

public ServiceProviderConfiguration Build()
{
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort);
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ public ServiceProviderConfiguration Create(FileGlobalConfiguration globalConfigu
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;

return new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithServiceDiscoveryProviderPort(serviceProviderPort)
.WithServiceDiscoveryProviderType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithHost(globalConfiguration?.ServiceDiscoveryProvider?.Host)
.WithPort(serviceProviderPort)
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
.Build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ public class FileServiceDiscoveryProvider
public string Host {get;set;}
public int Port { get; set; }
public string Type { get; set; }
public string Token { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,40 @@
using Consul;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Ocelot.Infrastructure.Consul;
using Ocelot.Responses;
using Ocelot.ServiceDiscovery;
using Ocelot.ServiceDiscovery.Configuration;

namespace Ocelot.Configuration.Repository
{
public class ConsulFileConfigurationRepository : IFileConfigurationRepository
{
private readonly ConsulClient _consul;
private string _ocelotConfiguration = "OcelotConfiguration";
private const string OcelotConfiguration = "OcelotConfiguration";
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 consulPort = serviceProviderConfig?.Port ?? 8500;
var configuration = new ConsulRegistryConfiguration(consulHost, consulPort, _ocelotConfiguration);
var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, serviceProviderConfig?.Token);
_cache = cache;
_consul = new ConsulClient(c =>
{
c.Address = new Uri($"http://{configuration.HostName}:{configuration.Port}");
});
_consul = factory.Get(config);
}

public async Task<Response<FileConfiguration>> Get()
{
var config = _cache.Get(_ocelotConfiguration, _ocelotConfiguration);
var config = _cache.Get(OcelotConfiguration, OcelotConfiguration);

if (config != null)
{
return new OkResponse<FileConfiguration>(config);
}

var queryResult = await _consul.KV.Get(_ocelotConfiguration);
var queryResult = await _consul.KV.Get(OcelotConfiguration);

if (queryResult.Response == null)
{
Expand All @@ -59,7 +59,7 @@ public async Task<Response> Set(FileConfiguration ocelotConfiguration)

var bytes = Encoding.UTF8.GetBytes(json);

var kvPair = new KVPair(_ocelotConfiguration)
var kvPair = new KVPair(OcelotConfiguration)
{
Value = bytes
};
Expand All @@ -68,7 +68,7 @@ public async Task<Response> Set(FileConfiguration ocelotConfiguration)

if (result.Response)
{
_cache.AddAndDelete(_ocelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), _ocelotConfiguration);
_cache.AddAndDelete(OcelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), OcelotConfiguration);

return new OkResponse();
}
Expand Down
12 changes: 7 additions & 5 deletions src/Ocelot/Configuration/ServiceProviderConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
{
public class ServiceProviderConfiguration
{
public ServiceProviderConfiguration(string type, string host, int port)
public ServiceProviderConfiguration(string type, string host, int port, string token)
{
Host = host;
Port = port;
Token = token;
Type = type;
}

public string Host { get; private set; }
public int Port { get; private set; }
public string Type { get; private set; }
public string Host { get; }
public int Port { get; }
public string Type { get; }
public string Token { get; }
}
}
}
8 changes: 6 additions & 2 deletions src/Ocelot/DependencyInjection/OcelotBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace Ocelot.DependencyInjection
using System.Net.Http;
using Butterfly.Client.AspNetCore;
using Ocelot.Infrastructure;
using Ocelot.Infrastructure.Consul;

public class OcelotBuilder : IOcelotBuilder
{
Expand Down Expand Up @@ -152,6 +153,7 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo
_services.TryAddSingleton<IConsulPollerConfiguration, InMemoryConsulPollerConfiguration>();
_services.TryAddSingleton<IAddHeadersToResponse, AddHeadersToResponse>();
_services.TryAddSingleton<IPlaceholders, Placeholders>();
_services.TryAddSingleton<IConsulClientFactory, ConsulClientFactory>();
}

public IOcelotAdministrationBuilder AddAdministration(string path, string secret)
Expand Down Expand Up @@ -236,10 +238,12 @@ public IOcelotBuilder AddStoreOcelotConfigurationInConsul()
{
var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0);
var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty);
var serviceDiscoveryToken = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Token", string.Empty);

var config = new ServiceProviderConfigurationBuilder()
.WithServiceDiscoveryProviderPort(serviceDiscoveryPort)
.WithServiceDiscoveryProviderHost(serviceDiscoveryHost)
.WithPort(serviceDiscoveryPort)
.WithHost(serviceDiscoveryHost)
.WithToken(serviceDiscoveryToken)
.Build();

_services.AddSingleton<ServiceProviderConfiguration>(config);
Expand Down
22 changes: 22 additions & 0 deletions src/Ocelot/Infrastructure/Consul/ConsulClientFactory.cs
Original file line number Diff line number Diff line change
@@ -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;
}
});
}
}
}
10 changes: 10 additions & 0 deletions src/Ocelot/Infrastructure/Consul/IConsulClientFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Consul;
using Ocelot.ServiceDiscovery.Configuration;

namespace Ocelot.Infrastructure.Consul
{
public interface IConsulClientFactory
{
ConsulClient Get(ConsulRegistryConfiguration config);
}
}
34 changes: 17 additions & 17 deletions src/Ocelot/Ocelot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Butterfly.Client.AspNetCore" Version="0.0.8" />
<PackageReference Include="FluentValidation" Version="7.2.1" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.1.0" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
<PackageReference Include="FluentValidation" Version="7.5.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.DiagnosticAdapter" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
<PackageReference Include="CacheManager.Core" Version="1.1.1" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.1" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.1" />
<PackageReference Include="Consul" Version="0.7.2.3" />
<PackageReference Include="Polly" Version="5.3.1" />
<PackageReference Include="IdentityServer4" Version="2.0.2" />
<PackageReference Include="CacheManager.Core" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Configuration" Version="1.1.2" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="1.1.2" />
<PackageReference Include="Consul" Version="0.7.2.4" />
<PackageReference Include="Polly" Version="5.8.0" />
<PackageReference Include="IdentityServer4" Version="2.1.3" />
<PackageReference Include="Rafty" Version="0.4.2" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ namespace Ocelot.ServiceDiscovery.Configuration
{
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;
KeyOfServiceInConsul = keyOfServiceInConsul;
Token = token;
}

public string KeyOfServiceInConsul { get; private set; }
public string HostName { get; private set; }
public int Port { get; private set; }
public string KeyOfServiceInConsul { get; }
public string Host { get; }
public int Port { get; }
public string Token { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading.Tasks;
using Consul;
using Ocelot.Infrastructure.Consul;
using Ocelot.Infrastructure.Extensions;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
Expand All @@ -12,30 +13,27 @@ namespace Ocelot.ServiceDiscovery.Providers
{
public class ConsulServiceDiscoveryProvider : IServiceDiscoveryProvider
{
private readonly ConsulRegistryConfiguration _consulConfig;
private readonly ConsulRegistryConfiguration _config;
private readonly IOcelotLogger _logger;
private readonly ConsulClient _consul;
private const string VersionPrefix = "version-";

public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration consulRegistryConfiguration, IOcelotLoggerFactory factory)
public ConsulServiceDiscoveryProvider(ConsulRegistryConfiguration config, IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
{;
_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 =>
{
config.Address = new Uri($"http://{_consulConfig.HostName}:{_consulConfig.Port}");
});
_consul = clientFactory.Get(_config);
}

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>();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Ocelot.Configuration;
using Ocelot.Infrastructure.Consul;
using Ocelot.Logging;
using Ocelot.ServiceDiscovery.Configuration;
using Ocelot.ServiceDiscovery.Providers;
Expand All @@ -10,10 +11,12 @@ namespace Ocelot.ServiceDiscovery
public class ServiceDiscoveryProviderFactory : IServiceDiscoveryProviderFactory
{
private readonly IOcelotLoggerFactory _factory;
private readonly IConsulClientFactory _clientFactory;

public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory)
public ServiceDiscoveryProviderFactory(IOcelotLoggerFactory factory, IConsulClientFactory clientFactory)
{
_factory = factory;
_clientFactory = clientFactory;
}

public IServiceDiscoveryProvider Get(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
Expand Down Expand Up @@ -43,8 +46,8 @@ private IServiceDiscoveryProvider GetServiceDiscoveryProvider(ServiceProviderCon
return new ServiceFabricServiceDiscoveryProvider(config);
}

var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName);
return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory);
var consulRegistryConfiguration = new ConsulRegistryConfiguration(serviceConfig.Host, serviceConfig.Port, serviceName, serviceConfig.Token);
return new ConsulServiceDiscoveryProvider(consulRegistryConfiguration, _factory, _clientFactory);
}
}
}
2 changes: 1 addition & 1 deletion test/Ocelot.AcceptanceTests/ButterflyTracingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void should_forward_tracing_information_from_ocelot_and_downstream_servic
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
.BDDfy();

var commandOnAllStateMachines = WaitFor(5000).Until(() => _butterflyCalled == 4);
var commandOnAllStateMachines = WaitFor(10000).Until(() => _butterflyCalled == 4);

commandOnAllStateMachines.ShouldBeTrue();
}
Expand Down
Loading

0 comments on commit 982eebf

Please sign in to comment.