Feature/service discovery config key (#347)

* #346 make service discoery config key configurable

* #346 missed this test

* #346 updated docs
This commit is contained in:
Tom Pallister 2018-05-08 21:18:38 +01:00 committed by GitHub
parent 6793278597
commit 4e17190b3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 705 additions and 628 deletions

View File

@ -146,6 +146,25 @@ I guess it means if you want to use Ocelot to its fullest you take on Consul as
This feature has a 3 second ttl cache before making a new request to your local consul agent. This feature has a 3 second ttl cache before making a new request to your local consul agent.
Configuration Key
-----------------
If you are using Consul for configuration (or other providers in the future) you might want to key your configurations so you can have multiple configurations :) This feature was requested in `issue 346 <https://github.com/ThreeMammals/Ocelot/issues/346>`_! In order to specify the key you need to set the ConfigurationKey property in the ServiceDiscoveryProvider section of the configuration json file e.g.
.. code-block:: json
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 9500,
"ConfigurationKey": "Oceolot_A"
}
}
In this example Ocelot will use Oceolot_A as the key for your configuration when looking it up in Consul.
If you do not set the ConfigurationKey Ocelot will use the string InternalConfiguration as the key.
Follow Redirects / Use CookieContainer Follow Redirects / Use CookieContainer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -6,6 +6,7 @@ namespace Ocelot.Configuration.Builder
private int _serviceDiscoveryProviderPort; private int _serviceDiscoveryProviderPort;
private string _type; private string _type;
private string _token; private string _token;
private string _configurationKey;
public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost) public ServiceProviderConfigurationBuilder WithHost(string serviceDiscoveryProviderHost)
{ {
@ -31,9 +32,15 @@ namespace Ocelot.Configuration.Builder
return this; return this;
} }
public ServiceProviderConfigurationBuilder WithConfigurationKey(string configurationKey)
{
_configurationKey = configurationKey;
return this;
}
public ServiceProviderConfiguration Build() public ServiceProviderConfiguration Build()
{ {
return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token); return new ServiceProviderConfiguration(_type, _serviceDiscoveryProviderHost, _serviceDiscoveryProviderPort, _token, _configurationKey);
} }
} }
} }

View File

@ -15,6 +15,7 @@ namespace Ocelot.Configuration.Creator
.WithPort(serviceProviderPort) .WithPort(serviceProviderPort)
.WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type) .WithType(globalConfiguration?.ServiceDiscoveryProvider?.Type)
.WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token) .WithToken(globalConfiguration?.ServiceDiscoveryProvider?.Token)
.WithConfigurationKey(globalConfiguration?.ServiceDiscoveryProvider?.ConfigurationKey)
.Build(); .Build();
} }
} }

View File

@ -6,5 +6,6 @@ namespace Ocelot.Configuration.File
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; } public string Token { get; set; }
public string ConfigurationKey { get; set; }
} }
} }

View File

@ -14,7 +14,7 @@ namespace Ocelot.Configuration.Repository
public class ConsulFileConfigurationRepository : IFileConfigurationRepository public class ConsulFileConfigurationRepository : IFileConfigurationRepository
{ {
private readonly IConsulClient _consul; private readonly IConsulClient _consul;
private const string OcelotConfiguration = "InternalConfiguration"; private readonly string _configurationKey;
private readonly Cache.IOcelotCache<FileConfiguration> _cache; private readonly Cache.IOcelotCache<FileConfiguration> _cache;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
@ -29,6 +29,7 @@ namespace Ocelot.Configuration.Repository
var internalConfig = repo.Get(); var internalConfig = repo.Get();
_configurationKey = "InternalConfiguration";
var consulHost = "localhost"; var consulHost = "localhost";
var consulPort = 8500; var consulPort = 8500;
string token = null; string token = null;
@ -38,23 +39,25 @@ namespace Ocelot.Configuration.Repository
consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host; consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host;
consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort; consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort;
token = internalConfig.Data.ServiceProviderConfiguration?.Token; token = internalConfig.Data.ServiceProviderConfiguration?.Token;
_configurationKey = !string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey) ?
internalConfig.Data.ServiceProviderConfiguration?.ConfigurationKey : _configurationKey;
} }
var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, token); var config = new ConsulRegistryConfiguration(consulHost, consulPort, _configurationKey, token);
_consul = factory.Get(config); _consul = factory.Get(config);
} }
public async Task<Response<FileConfiguration>> Get() public async Task<Response<FileConfiguration>> Get()
{ {
var config = _cache.Get(OcelotConfiguration, OcelotConfiguration); var config = _cache.Get(_configurationKey, _configurationKey);
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(_configurationKey);
if (queryResult.Response == null) if (queryResult.Response == null)
{ {
@ -76,7 +79,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(_configurationKey)
{ {
Value = bytes Value = bytes
}; };
@ -85,7 +88,7 @@ namespace Ocelot.Configuration.Repository
if (result.Response) if (result.Response)
{ {
_cache.AddAndDelete(OcelotConfiguration, ocelotConfiguration, TimeSpan.FromSeconds(3), OcelotConfiguration); _cache.AddAndDelete(_configurationKey, ocelotConfiguration, TimeSpan.FromSeconds(3), _configurationKey);
return new OkResponse(); return new OkResponse();
} }

View File

@ -2,8 +2,9 @@
{ {
public class ServiceProviderConfiguration public class ServiceProviderConfiguration
{ {
public ServiceProviderConfiguration(string type, string host, int port, string token) public ServiceProviderConfiguration(string type, string host, int port, string token, string configurationKey)
{ {
ConfigurationKey = configurationKey;
Host = host; Host = host;
Port = port; Port = port;
Token = token; Token = token;
@ -14,5 +15,6 @@
public int Port { get; } public int Port { get; }
public string Type { get; } public string Type { get; }
public string Token { get; } public string Token { get; }
public string ConfigurationKey { get; }
} }
} }

View File

@ -48,6 +48,7 @@ namespace Ocelot.UnitTests.Configuration
_client _client
.Setup(x => x.KV) .Setup(x => x.KV)
.Returns(_kvEndpoint.Object); .Returns(_kvEndpoint.Object);
_factory _factory
.Setup(x => x.Get(It.IsAny<ConsulRegistryConfiguration>())) .Setup(x => x.Get(It.IsAny<ConsulRegistryConfiguration>()))
.Returns(_client.Object); .Returns(_client.Object);
@ -104,6 +105,46 @@ namespace Ocelot.UnitTests.Configuration
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_set_config_key()
{
var config = FakeFileConfiguration();
this.Given(_ => GivenIHaveAConfiguration(config))
.And(_ => GivenTheConfigKeyComesFromFileConfig("Tom"))
.And(_ => GivenFetchFromConsulSucceeds())
.When(_ => WhenIGetTheConfiguration())
.And(_ => ThenTheConfigKeyIs("Tom"))
.BDDfy();
}
[Fact]
public void should_set_default_config_key()
{
var config = FakeFileConfiguration();
this.Given(_ => GivenIHaveAConfiguration(config))
.And(_ => GivenFetchFromConsulSucceeds())
.When(_ => WhenIGetTheConfiguration())
.And(_ => ThenTheConfigKeyIs("InternalConfiguration"))
.BDDfy();
}
private void ThenTheConfigKeyIs(string expected)
{
_kvEndpoint
.Verify(x => x.Get(expected, It.IsAny<CancellationToken>()), Times.Once);
}
private void GivenTheConfigKeyComesFromFileConfig(string key)
{
_internalRepo
.Setup(x => x.Get())
.Returns(new OkResponse<IInternalConfiguration>(new InternalConfiguration(new List<ReRoute>(), "", new ServiceProviderConfigurationBuilder().WithConfigurationKey(key).Build(), "")));
_repo = new ConsulFileConfigurationRepository(_cache.Object, _internalRepo.Object, _factory.Object, _loggerFactory.Object);
}
private void ThenTheConfigurationIsNull() private void ThenTheConfigurationIsNull()
{ {
_getResult.Data.ShouldBeNull(); _getResult.Data.ShouldBeNull();

View File

@ -29,7 +29,8 @@ namespace Ocelot.UnitTests.Configuration
Host = "127.0.0.1", Host = "127.0.0.1",
Port = 1234, Port = 1234,
Type = "ServiceFabric", Type = "ServiceFabric",
Token = "testtoken" Token = "testtoken",
ConfigurationKey = "woo"
} }
}; };
@ -38,6 +39,7 @@ namespace Ocelot.UnitTests.Configuration
.WithPort(1234) .WithPort(1234)
.WithType("ServiceFabric") .WithType("ServiceFabric")
.WithToken("testtoken") .WithToken("testtoken")
.WithConfigurationKey("woo")
.Build(); .Build();
this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig)) this.Given(x => x.GivenTheFollowingGlobalConfig(globalConfig))
@ -62,6 +64,7 @@ namespace Ocelot.UnitTests.Configuration
_result.Port.ShouldBe(expected.Port); _result.Port.ShouldBe(expected.Port);
_result.Token.ShouldBe(expected.Token); _result.Token.ShouldBe(expected.Token);
_result.Type.ShouldBe(expected.Type); _result.Type.ShouldBe(expected.Type);
_result.ConfigurationKey.ShouldBe(expected.ConfigurationKey);
} }
} }
} }

View File

@ -26,7 +26,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, string.Empty); _serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123, string.Empty, "configKey");
} }
[Fact] [Fact]