mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 08:18:16 +08:00
Feature/hacking consul file config (#157)
* moving things around to see if I can get consul to store fileconfiguration rather than ocelotconfiguration * more refactoring to see if we can get a test for the feature * acceptance test passing for updating in consul..need to sort object comparison out * fixed the failing tests
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -20,7 +22,7 @@ namespace Ocelot.AcceptanceTests
|
||||
private IWebHost _builder;
|
||||
private readonly Steps _steps;
|
||||
private IWebHost _fakeConsulBuilder;
|
||||
private IOcelotConfiguration _config;
|
||||
private FileConfiguration _config;
|
||||
|
||||
public ConfigurationInConsul()
|
||||
{
|
||||
@ -67,7 +69,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_fix_issue_142()
|
||||
public void should_load_configuration_out_of_consul()
|
||||
{
|
||||
var consulPort = 8500;
|
||||
var configuration = new FileConfiguration
|
||||
@ -84,28 +86,31 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
|
||||
|
||||
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
|
||||
.WithServiceDiscoveryProviderHost("localhost")
|
||||
.WithServiceDiscoveryProviderPort(consulPort)
|
||||
.Build();
|
||||
var consulConfig = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/status",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHost = "localhost",
|
||||
DownstreamPort = 51779,
|
||||
UpstreamPathTemplate = "/cs/status",
|
||||
UpstreamHttpMethod = new List<string> {"Get"}
|
||||
}
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/status")
|
||||
.WithUpstreamTemplatePattern("^(?i)/cs/status/$")
|
||||
.WithDownstreamScheme("http")
|
||||
.WithDownstreamHost("localhost")
|
||||
.WithDownstreamPort(51779)
|
||||
.WithUpstreamPathTemplate("/cs/status")
|
||||
.WithUpstreamHttpMethod(new List<string> {"Get"})
|
||||
.WithReRouteKey("/cs/status|Get")
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, false))
|
||||
.Build();
|
||||
|
||||
var reRoutes = new List<ReRoute> { reRoute };
|
||||
|
||||
var config = new OcelotConfiguration(reRoutes, null, serviceProviderConfig);
|
||||
|
||||
this.Given(x => GivenTheConsulConfigurationIs(config))
|
||||
this.Given(x => GivenTheConsulConfigurationIs(consulConfig))
|
||||
.And(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "/status", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
@ -116,7 +121,95 @@ namespace Ocelot.AcceptanceTests
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConsulConfigurationIs(OcelotConfiguration config)
|
||||
|
||||
[Fact]
|
||||
public void should_load_configuration_out_of_consul_if_it_is_changed()
|
||||
{
|
||||
var consulPort = 8506;
|
||||
var configuration = new FileConfiguration
|
||||
{
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";
|
||||
|
||||
var consulConfig = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/status",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHost = "localhost",
|
||||
DownstreamPort = 51779,
|
||||
UpstreamPathTemplate = "/cs/status",
|
||||
UpstreamHttpMethod = new List<string> {"Get"}
|
||||
}
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var secondConsulConfig = new FileConfiguration
|
||||
{
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamPathTemplate = "/status",
|
||||
DownstreamScheme = "http",
|
||||
DownstreamHost = "localhost",
|
||||
DownstreamPort = 51779,
|
||||
UpstreamPathTemplate = "/cs/status/awesome",
|
||||
UpstreamHttpMethod = new List<string> {"Get"}
|
||||
}
|
||||
},
|
||||
GlobalConfiguration = new FileGlobalConfiguration()
|
||||
{
|
||||
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
|
||||
{
|
||||
Host = "localhost",
|
||||
Port = consulPort
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => GivenTheConsulConfigurationIs(consulConfig))
|
||||
.And(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", "/status", 200, "Hello from Laura"))
|
||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig())
|
||||
.And(x => _steps.WhenIGetUrlOnTheApiGateway("/cs/status"))
|
||||
.And(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.And(x => GivenTheConsulConfigurationIs(secondConsulConfig))
|
||||
.And(x => GivenIWaitForTheConfigToReplicateToOcelot())
|
||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/cs/status/awesome"))
|
||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenIWaitForTheConfigToReplicateToOcelot()
|
||||
{
|
||||
Thread.Sleep(10000);
|
||||
}
|
||||
|
||||
private void GivenTheConsulConfigurationIs(FileConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
@ -154,7 +247,7 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
var json = reader.ReadToEnd();
|
||||
|
||||
_config = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
|
||||
_config = JsonConvert.DeserializeObject<FileConfiguration>(json);
|
||||
|
||||
var response = JsonConvert.SerializeObject(true);
|
||||
|
||||
|
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Configuration.Repository;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Shouldly;
|
||||
using static Ocelot.UnitTests.Wait;
|
||||
|
||||
|
||||
namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
public class ConsulFileConfigurationPollerTests : IDisposable
|
||||
{
|
||||
private ConsulFileConfigurationPoller _poller;
|
||||
private Mock<IOcelotLoggerFactory> _factory;
|
||||
private Mock<IFileConfigurationRepository> _repo;
|
||||
private Mock<IFileConfigurationSetter> _setter;
|
||||
private FileConfiguration _fileConfig;
|
||||
|
||||
public ConsulFileConfigurationPollerTests()
|
||||
{
|
||||
var logger = new Mock<IOcelotLogger>();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_factory.Setup(x => x.CreateLogger<ConsulFileConfigurationPoller>()).Returns(logger.Object);
|
||||
_repo = new Mock<IFileConfigurationRepository>();
|
||||
_setter = new Mock<IFileConfigurationSetter>();
|
||||
_fileConfig = new FileConfiguration();
|
||||
_repo.Setup(x => x.Get()).ReturnsAsync(new OkResponse<FileConfiguration>(_fileConfig));
|
||||
_poller = new ConsulFileConfigurationPoller(_factory.Object, _repo.Object, _setter.Object);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
_poller.Dispose();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_start()
|
||||
{
|
||||
this.Given(x => ThenTheSetterIsCalled(_fileConfig))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_setter_when_gets_new_config()
|
||||
{
|
||||
|
||||
var newConfig = new FileConfiguration {
|
||||
ReRoutes = new List<FileReRoute>
|
||||
{
|
||||
new FileReRoute
|
||||
{
|
||||
DownstreamHost = "test"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.Given(x => WhenTheConfigIsChangedInConsul(newConfig))
|
||||
.Then(x => ThenTheSetterIsCalled(newConfig))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenTheConfigIsChangedInConsul(FileConfiguration newConfig)
|
||||
{
|
||||
_repo.Setup(x => x.Get()).ReturnsAsync(new OkResponse<FileConfiguration>(newConfig));
|
||||
}
|
||||
|
||||
private void ThenTheSetterIsCalled(FileConfiguration fileConfig)
|
||||
{
|
||||
var result = WaitFor(2000).Until(() => {
|
||||
try
|
||||
{
|
||||
_setter.Verify(x => x.Set(fileConfig), Times.Once);
|
||||
return true;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -45,12 +45,12 @@ namespace Ocelot.UnitTests.Configuration
|
||||
_fileConfiguration = fileConfiguration;
|
||||
_repo
|
||||
.Setup(x => x.Get())
|
||||
.Returns(new OkResponse<FileConfiguration>(fileConfiguration));
|
||||
.ReturnsAsync(new OkResponse<FileConfiguration>(fileConfiguration));
|
||||
}
|
||||
|
||||
private void WhenIGetTheReRoutes()
|
||||
{
|
||||
_result = _provider.Get().Data;
|
||||
_result = _provider.Get().Result.Data;
|
||||
}
|
||||
|
||||
private void ThenTheRepoIsCalledCorrectly()
|
||||
|
@ -100,7 +100,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
private void WhenISetTheConfiguration()
|
||||
{
|
||||
_repo.Set(_fileConfiguration);
|
||||
_result = _repo.Get().Data;
|
||||
_result = _repo.Get().Result.Data;
|
||||
}
|
||||
|
||||
private void ThenTheConfigurationIsStoredAs(FileConfiguration expected)
|
||||
@ -135,7 +135,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
|
||||
private void WhenIGetTheReRoutes()
|
||||
{
|
||||
_result = _repo.Get().Data;
|
||||
_result = _repo.Get().Result.Data;
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(FileConfiguration expected)
|
||||
|
@ -78,7 +78,7 @@ namespace Ocelot.UnitTests.Configuration
|
||||
{
|
||||
_repo
|
||||
.Setup(x => x.Set(It.IsAny<FileConfiguration>()))
|
||||
.Returns(response);
|
||||
.ReturnsAsync(response);
|
||||
}
|
||||
|
||||
private void ThenAnErrorResponseIsReturned()
|
||||
|
@ -107,12 +107,12 @@ namespace Ocelot.UnitTests.Controllers
|
||||
{
|
||||
_configGetter
|
||||
.Setup(x => x.Get())
|
||||
.Returns(fileConfiguration);
|
||||
.ReturnsAsync(fileConfiguration);
|
||||
}
|
||||
|
||||
private void WhenIGetTheFileConfiguration()
|
||||
{
|
||||
_result = _controller.Get();
|
||||
_result = _controller.Get().Result;
|
||||
}
|
||||
|
||||
private void TheTheGetFileConfigurationIsCalledCorrectly()
|
||||
|
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.DependencyInjection
|
||||
{
|
||||
public class ServiceCollectionExtensionTests
|
||||
{
|
||||
private Exception _ex;
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_services()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServices())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
IWebHostBuilder builder = new WebHostBuilder();
|
||||
IConfigurationRoot configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
services.AddSingleton(builder);
|
||||
services.AddOcelot(configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
}
|
55
test/Ocelot.UnitTests/Waiter.cs
Normal file
55
test/Ocelot.UnitTests/Waiter.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ocelot.UnitTests
|
||||
{
|
||||
public class Wait
|
||||
{
|
||||
public static Waiter WaitFor(int milliSeconds)
|
||||
{
|
||||
return new Waiter(milliSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
public class Waiter
|
||||
{
|
||||
private readonly int _milliSeconds;
|
||||
|
||||
public Waiter(int milliSeconds)
|
||||
{
|
||||
_milliSeconds = milliSeconds;
|
||||
}
|
||||
|
||||
public bool Until(Func<bool> condition)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var passed = false;
|
||||
while (stopwatch.ElapsedMilliseconds < _milliSeconds)
|
||||
{
|
||||
if (condition.Invoke())
|
||||
{
|
||||
passed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
public bool Until<T>(Func<bool> condition)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var passed = false;
|
||||
while (stopwatch.ElapsedMilliseconds < _milliSeconds)
|
||||
{
|
||||
if (condition.Invoke())
|
||||
{
|
||||
passed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user