added a new implementation that stores the ocelot config in consul kv store, had to change some major things and add cache settings as default

This commit is contained in:
TomPallister
2017-04-16 19:35:59 +01:00
parent ab9c8e30b2
commit c3cd181b90
34 changed files with 623 additions and 309 deletions

View File

@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Ocelot.Configuration;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
using Ocelot.ServiceDiscovery;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.AcceptanceTests
{
public class ConfigurationInConsul : IDisposable
{
private IWebHost _builder;
private readonly Steps _steps;
private IWebHost _fakeConsulBuilder;
private IOcelotConfiguration _config;
public ConfigurationInConsul()
{
_steps = new Steps();
}
[Fact]
public void should_return_response_200_with_simple_url()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHost = "localhost",
DownstreamPort = 51779,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = "Get",
}
},
GlobalConfiguration = new FileGlobalConfiguration()
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider()
{
Provider = "Consul",
Host = "localhost",
Port = 9500
}
}
};
var fakeConsulServiceDiscoveryUrl = "http://localhost:9500";
var consulConfig = new ConsulRegistryConfiguration("localhost", 9500, "Ocelot");
this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51779", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfig(consulConfig))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}
private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url)
{
_fakeConsulBuilder = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration")
{
var json = JsonConvert.SerializeObject(_config);
var bytes = Encoding.UTF8.GetBytes(json);
var base64 = Convert.ToBase64String(bytes);
var kvp = new FakeConsulGetResponse(base64);
await context.Response.WriteJsonAsync(new FakeConsulGetResponse[]{kvp});
}
else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration")
{
try
{
var reader = new StreamReader(context.Request.Body);
var json = reader.ReadToEnd();
_config = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
var response = JsonConvert.SerializeObject(true);
await context.Response.WriteAsync(response);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
});
})
.Build();
_fakeConsulBuilder.Start();
}
public class FakeConsulGetResponse
{
public FakeConsulGetResponse(string value)
{
Value = value;
}
public int CreateIndex => 100;
public int ModifyIndex => 200;
public int LockIndex => 200;
public string Key => "OcelotConfiguration";
public int Flags => 0;
public string Value { get; private set; }
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";
}
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
{
_builder = new WebHostBuilder()
.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
})
.Build();
_builder.Start();
}
public void Dispose()
{
_builder?.Dispose();
_steps.Dispose();
}
}
}

View File

@ -15,9 +15,11 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Ocelot.Configuration.Repository;
using Ocelot.DependencyInjection;
using Ocelot.ManualTest;
using Ocelot.Middleware;
using Ocelot.ServiceDiscovery;
using Shouldly;
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
@ -84,6 +86,22 @@ namespace Ocelot.AcceptanceTests
_ocelotClient = _ocelotServer.CreateClient();
}
public void GivenOcelotIsRunningUsingConsulToStoreConfig(ConsulRegistryConfiguration consulConfig)
{
_webHostBuilder = new WebHostBuilder();
_webHostBuilder.ConfigureServices(s =>
{
s.AddSingleton(_webHostBuilder);
s.AddOcelotStoreConfigurationInConsul(consulConfig);
});
_ocelotServer = new TestServer(_webHostBuilder
.UseStartup<Startup>());
_ocelotClient = _ocelotServer.CreateClient();
}
internal void ThenTheResponseShouldBe(FileConfiguration expected)
{
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
@ -138,8 +156,7 @@ namespace Ocelot.AcceptanceTests
.WithDictionaryHandle();
};
s.AddOcelotOutputCaching(settings);
s.AddOcelot(configuration);
s.AddOcelot(configuration, settings);
})
.ConfigureLogging(l =>
{

View File

@ -37,8 +37,8 @@ namespace Ocelot.ManualTest
})
.WithDictionaryHandle();
};
services.AddOcelotOutputCaching(settings);
services.AddOcelot(Configuration);
services.AddOcelot(Configuration, settings);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

View File

@ -690,10 +690,10 @@ namespace Ocelot.UnitTests.Configuration
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
{
_config.Data.ReRoutes[0].QosOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
_config.Data.ReRoutes[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
_config.Data.ReRoutes[0].QosOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
_config.Data.ReRoutes[0].QosOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
_config.Data.ReRoutes[0].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
_config.Data.ReRoutes[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
}
}
}

View File

@ -49,7 +49,7 @@ namespace Ocelot.UnitTests.Configuration
private void WhenIGetTheConfiguration()
{
_getResult = _repo.Get();
_getResult = _repo.Get().Result;
}
private void GivenThereIsASavedConfiguration()
@ -65,7 +65,7 @@ namespace Ocelot.UnitTests.Configuration
private void WhenIAddOrReplaceTheConfig()
{
_result = _repo.AddOrReplace(_config);
_result = _repo.AddOrReplace(_config).Result;
}
private void ThenNoErrorsAreReturned()

View File

@ -53,12 +53,12 @@ namespace Ocelot.UnitTests.Configuration
{
_configurationRepository
.Setup(x => x.Get())
.Returns(config);
.ReturnsAsync(config);
}
private void WhenIGetTheConfig()
{
_result = _ocelotConfigurationProvider.Get();
_result = _ocelotConfigurationProvider.Get().Result;
}
private void TheFollowingIsReturned(Response<IOcelotConfiguration> expected)

View File

@ -59,7 +59,7 @@ namespace Ocelot.UnitTests.Configuration
.WithQuotaExceededMessage("QuotaExceededMessage")
.WithRateLimitCounterPrefix("RateLimitCounterPrefix")
.WithRateLimitRule(new RateLimitRule(fileReRoute.RateLimitOptions.Period,
TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan),
fileReRoute.RateLimitOptions.PeriodTimespan,
fileReRoute.RateLimitOptions.Limit))
.Build();
@ -102,7 +102,7 @@ namespace Ocelot.UnitTests.Configuration
_result.RateLimitCounterPrefix.ShouldBe(expected.RateLimitCounterPrefix);
_result.RateLimitRule.Limit.ShouldBe(expected.RateLimitRule.Limit);
_result.RateLimitRule.Period.ShouldBe(expected.RateLimitRule.Period);
_result.RateLimitRule.PeriodTimespan.Ticks.ShouldBe(expected.RateLimitRule.PeriodTimespan.Ticks);
TimeSpan.FromSeconds(_result.RateLimitRule.PeriodTimespan).Ticks.ShouldBe(TimeSpan.FromSeconds(expected.RateLimitRule.PeriodTimespan).Ticks);
}
}
}

View File

@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
_downstreamRouteFinder
.Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>()))
.Returns(_downstreamRoute);
.ReturnsAsync(_downstreamRoute);
}
public void Dispose()

View File

@ -199,7 +199,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
_reRoutesConfig = reRoutesConfig;
_mockConfig
.Setup(x => x.Get())
.Returns(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath)));
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(new OcelotConfiguration(_reRoutesConfig, adminPath)));
}
private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath)
@ -209,7 +209,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private void WhenICallTheFinder()
{
_result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod);
_result = _downstreamRouteFinder.FindDownstreamRoute(_upstreamUrlPath, _upstreamHttpMethod).Result;
}
private void ThenTheFollowingIsReturned(DownstreamRoute expected)

View File

@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.RateLimit
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", TimeSpan.FromSeconds(100), 3), 429))
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429))
.WithUpstreamHttpMethod("Get")
.Build());
@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.RateLimit
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", TimeSpan.FromSeconds(100),3),429))
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", 100,3),429))
.WithUpstreamHttpMethod("Get")
.Build());