mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 10:35:28 +08:00 
			
		
		
		
	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:
		@@ -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 
 | 
				
			||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user