diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs b/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs index f70712ed..1a118086 100644 --- a/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs +++ b/src/Ocelot.Library/Infrastructure/Configuration/Configuration.cs @@ -8,11 +8,7 @@ namespace Ocelot.Library.Infrastructure.Configuration { Routes = new List(); } - public Configuration(List routes) - { - Routes = routes; - } - public List Routes { get; private set; } + public List Routes { get; set; } } } diff --git a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationReader.cs b/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationReader.cs deleted file mode 100644 index 139cff46..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/ConfigurationReader.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Ocelot.Library.Infrastructure.Configuration -{ - using System.IO; - using YamlDotNet.Serialization; - using YamlDotNet.Serialization.NamingConventions; - - public class ConfigurationReader : IConfigurationReader - { - public Configuration Read(string configurationFilePath) - { - var contents = File.ReadAllText(configurationFilePath); - - var input = new StringReader(contents); - - var deserializer = new Deserializer(namingConvention: new CamelCaseNamingConvention()); - - var configuration = deserializer.Deserialize(input); - - return configuration;; - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationReader.cs b/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationReader.cs deleted file mode 100644 index d53b0526..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/IConfigurationReader.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ocelot.Library.Infrastructure.Configuration -{ - public interface IConfigurationReader - { - Configuration Read(string configurationFilePath); - } -} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/Route.cs b/src/Ocelot.Library/Infrastructure/Configuration/Route.cs index aa551658..a30d3bbf 100644 --- a/src/Ocelot.Library/Infrastructure/Configuration/Route.cs +++ b/src/Ocelot.Library/Infrastructure/Configuration/Route.cs @@ -2,17 +2,7 @@ { public class Route { - public Route() - { - - } - public Route(string downstream, string upstream) - { - Downstream = downstream; - Upstream = upstream; - } - - public string Downstream { get; private set; } - public string Upstream { get; private set; } + public string Downstream { get; set; } + public string Upstream { get; set; } } } diff --git a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationExtensions.cs b/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationExtensions.cs deleted file mode 100644 index 802016c8..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.IO; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.FileProviders; - -namespace Ocelot.Library.Infrastructure.Configuration -{ - public static class YamlConfigurationExtensions - { - public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path) - { - return AddYamlFile(builder, provider: null, path: path, optional: false, reloadOnChange: false); - } - - public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path, bool optional) - { - return AddYamlFile(builder, provider: null, path: path, optional: optional, reloadOnChange: false); - } - - public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange) - { - return AddYamlFile(builder, provider: null, path: path, optional: optional, reloadOnChange: reloadOnChange); - } - - public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange) - { - if (provider == null && Path.IsPathRooted(path)) - { - provider = new PhysicalFileProvider(Path.GetDirectoryName(path)); - path = Path.GetFileName(path); - } - var source = new YamlConfigurationSource - { - FileProvider = provider, - Path = path, - Optional = optional, - ReloadOnChange = reloadOnChange - }; - builder.Add(source); - return builder; - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationFileParser.cs b/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationFileParser.cs deleted file mode 100644 index 5e6d7c34..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationFileParser.cs +++ /dev/null @@ -1,121 +0,0 @@ -namespace Ocelot.Library.Infrastructure.Configuration -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using Microsoft.Extensions.Configuration; - using YamlDotNet.RepresentationModel; - - internal class YamlConfigurationFileParser - { - private readonly IDictionary _data = new SortedDictionary(StringComparer.OrdinalIgnoreCase); - private readonly Stack _context = new Stack(); - private string _currentPath; - - public IDictionary Parse(Stream input) - { - _data.Clear(); - _context.Clear(); - - // https://dotnetfiddle.net/rrR2Bb - var yaml = new YamlStream(); - yaml.Load(new StreamReader(input)); - - if (yaml.Documents.Any()) - { - var mapping = (YamlMappingNode)yaml.Documents[0].RootNode; - - // The document node is a mapping node - VisitYamlMappingNode(mapping); - } - - return _data; - } - - private void VisitYamlNodePair(KeyValuePair yamlNodePair) - { - var context = ((YamlScalarNode)yamlNodePair.Key).Value; - VisitYamlNode(context, yamlNodePair.Value); - } - - private void VisitYamlNode(string context, YamlNode node) - { - if (node is YamlScalarNode) - { - VisitYamlScalarNode(context, (YamlScalarNode)node); - } - if (node is YamlMappingNode) - { - VisitYamlMappingNode(context, (YamlMappingNode)node); - } - if (node is YamlSequenceNode) - { - VisitYamlSequenceNode(context, (YamlSequenceNode)node); - } - } - - private void VisitYamlScalarNode(string context, YamlScalarNode yamlValue) - { - //a node with a single 1-1 mapping - EnterContext(context); - var currentKey = _currentPath; - - if (_data.ContainsKey(currentKey)) - { - throw new FormatException("Key is duplicate ${currentKey}"); - } - - _data[currentKey] = yamlValue.Value; - ExitContext(); - } - - private void VisitYamlMappingNode(YamlMappingNode node) - { - foreach (var yamlNodePair in node.Children) - { - VisitYamlNodePair(yamlNodePair); - } - } - - private void VisitYamlMappingNode(string context, YamlMappingNode yamlValue) - { - //a node with an associated sub-document - EnterContext(context); - - VisitYamlMappingNode(yamlValue); - - ExitContext(); - } - - private void VisitYamlSequenceNode(string context, YamlSequenceNode yamlValue) - { - //a node with an associated list - EnterContext(context); - - VisitYamlSequenceNode(yamlValue); - - ExitContext(); - } - - private void VisitYamlSequenceNode(YamlSequenceNode node) - { - for (int i = 0; i < node.Children.Count; i++) - { - VisitYamlNode(i.ToString(), node.Children[i]); - } - } - - private void EnterContext(string context) - { - _context.Push(context); - _currentPath = ConfigurationPath.Combine(_context.Reverse()); - } - - private void ExitContext() - { - _context.Pop(); - _currentPath = ConfigurationPath.Combine(_context.Reverse()); - } - } -} \ No newline at end of file diff --git a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationProvider.cs b/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationProvider.cs deleted file mode 100644 index fc81e102..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationProvider.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Ocelot.Library.Infrastructure.Configuration -{ - using System.IO; - using Microsoft.Extensions.Configuration; - - public class YamlConfigurationProvider : FileConfigurationProvider - { - public YamlConfigurationProvider(YamlConfigurationSource source) : base(source) { } - - public override void Load(Stream stream) - { - var parser = new YamlConfigurationFileParser(); - - Data = parser.Parse(stream); - } - } -} diff --git a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationSource.cs b/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationSource.cs deleted file mode 100644 index d1684517..00000000 --- a/src/Ocelot.Library/Infrastructure/Configuration/YamlConfigurationSource.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ocelot.Library.Infrastructure.Configuration -{ - using Microsoft.Extensions.Configuration; - - public class YamlConfigurationSource : FileConfigurationSource - { - public override IConfigurationProvider Build(IConfigurationBuilder builder) - { - FileProvider = FileProvider ?? builder.GetFileProvider(); - return new YamlConfigurationProvider(this); - } - } -} diff --git a/src/Ocelot/Startup.cs b/src/Ocelot/Startup.cs index 779a0e74..93346a40 100644 --- a/src/Ocelot/Startup.cs +++ b/src/Ocelot/Startup.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/src/Ocelot/project.json b/src/Ocelot/project.json index ba309f23..d77d3493 100644 --- a/src/Ocelot/project.json +++ b/src/Ocelot/project.json @@ -15,7 +15,8 @@ "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.Extensions.Logging.Debug": "1.0.0", "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", - "Ocelot.Library": "1.0.0-*" + "Ocelot.Library": "1.0.0-*", + "NetEscapades.Configuration.Yaml": "1.1.0" }, "tools": { diff --git a/test/Ocelot.AcceptanceTests/ConfigurationReaderTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationReaderTests.cs deleted file mode 100644 index 14878829..00000000 --- a/test/Ocelot.AcceptanceTests/ConfigurationReaderTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace Ocelot.AcceptanceTests -{ - using System.Collections.Generic; - using Library.Infrastructure.Configuration; - using Shouldly; - using TestStack.BDDfy; - using Xunit; - - public class ConfigurationReaderTests - { - private readonly IConfigurationReader _configurationReader; - private string _configPath; - private Configuration _result; - - public ConfigurationReaderTests() - { - _configurationReader = new ConfigurationReader(); - } - - [Fact] - public void can_read_configuration() - { - const string path = "./ConfigurationReaderTests.can_read_configuration.yaml"; - - var expected = - new Configuration(new List - { - new Route("productservice/category/{categoryId}/products/{productId}/variants/{variantId}", - "https://www.moonpig.com/api/products/{categoryId}/{productId}/{variantId}") - }); - - this.Given(x => x.GivenAConfigPathOf(path)) - .When(x => x.WhenICallTheConfigurationReader()) - .Then(x => x.ThenTheFollowingConfigurationIsReturned(expected)) - .BDDfy(); - } - - private void GivenAConfigPathOf(string configPath) - { - _configPath = configPath; - } - - private void WhenICallTheConfigurationReader() - { - _result = _configurationReader.Read(_configPath); - } - - private void ThenTheFollowingConfigurationIsReturned(Configuration expected) - { - _result.Routes[0].Downstream.ShouldBe(expected.Routes[0].Downstream); - _result.Routes[0].Upstream.ShouldBe(expected.Routes[0].Upstream); - } - } -} diff --git a/test/Ocelot.AcceptanceTests/OcelotTests.cs b/test/Ocelot.AcceptanceTests/OcelotTests.cs index 08a2734c..6989ce99 100644 --- a/test/Ocelot.AcceptanceTests/OcelotTests.cs +++ b/test/Ocelot.AcceptanceTests/OcelotTests.cs @@ -1,37 +1,36 @@ -using System; -using System.Net.Http; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Xunit; -using Ocelot.AcceptanceTests.Fake; -using Shouldly; - namespace Ocelot.AcceptanceTests { + using System; + using System.Net.Http; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.TestHost; + using Xunit; + using Ocelot.AcceptanceTests.Fake; + using Shouldly; + using System.Collections.Generic; + using System.IO; using System.Net; + using Library.Infrastructure.Configuration; using TestStack.BDDfy; + using YamlDotNet.Serialization; public class OcelotTests : IDisposable { private readonly FakeService _fakeService; - private readonly TestServer _server; - private readonly HttpClient _client; + private TestServer _server; + private HttpClient _client; private HttpResponseMessage _response; public OcelotTests() { - _server = new TestServer(new WebHostBuilder() - .UseStartup()); - - _client = _server.CreateClient(); - _fakeService = new FakeService(); } [Fact] public void should_return_response_404() { - this.When(x => x.WhenIRequestTheUrl("/")) + this.Given(x => x.GivenTheApiGatewayIsRunning()) + .When(x => x.WhenIRequestTheUrlOnTheApiGateway("/")) .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) .BDDfy(); } @@ -39,13 +38,57 @@ namespace Ocelot.AcceptanceTests [Fact] public void should_return_response_200() { - this.When(x => x.WhenIRequestTheUrl("/")) + this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879")) + .And(x => x.GivenThereIsAConfiguration(new Configuration + { + Routes = new List + { + new Route + { + Downstream = "http://localhost:51879/", + Upstream = "/heee" + } + } + })) + .And(x => x.GivenTheApiGatewayIsRunning()) + .When(x => x.WhenIRequestTheUrlOnTheApiGateway("/")) .Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) .And(x => x.ThenTheResponseBodyShouldBe("Hello from Laura")) .BDDfy(); } - private void WhenIRequestTheUrl(string url) + /// + /// This is annoying cos it should be in the constructor but we need to set up the yaml file before calling startup so its a step. + /// + private void GivenTheApiGatewayIsRunning() + { + _server = new TestServer(new WebHostBuilder() + .UseStartup()); + + _client = _server.CreateClient(); + } + + private void GivenThereIsAConfiguration(Configuration configuration) + { + var serializer = new Serializer(); + + if (File.Exists("./configuration.yaml")) + { + File.Delete("./configuration.yaml"); + } + + using (TextWriter writer = File.CreateText("./configuration.yaml")) + { + serializer.Serialize(writer, configuration); + } + } + + private void GivenThereIsAServiceRunningOn(string url) + { + _fakeService.Start(url); + } + + private void WhenIRequestTheUrlOnTheApiGateway(string url) { _response = _client.GetAsync("/").Result; } diff --git a/test/Ocelot.AcceptanceTests/configuration.yaml b/test/Ocelot.AcceptanceTests/configuration.yaml index 98c05a41..2e47e77d 100644 --- a/test/Ocelot.AcceptanceTests/configuration.yaml +++ b/test/Ocelot.AcceptanceTests/configuration.yaml @@ -1,3 +1,3 @@ -routes: - - downstream: "productservice/category/{categoryId}/products/{productId}/variants/{variantId}" - upstream: "https://www.moonpig.com/api/products/{categoryId}/{productId}/{variantId}" +Routes: +- Downstream: http://localhost:51879/ + Upstream: /heee