diff --git a/.gitignore b/.gitignore index 836e0bfe..476938f0 100644 --- a/.gitignore +++ b/.gitignore @@ -243,7 +243,7 @@ tools/ .DS_Store # Ocelot acceptance test config -test/Ocelot.AcceptanceTests/configuration.json +test/Ocelot.AcceptanceTests/ocelot.json # Read the docstates _build/ @@ -251,4 +251,4 @@ _static/ _templates/ # JetBrains Rider -.idea/ \ No newline at end of file +.idea/ diff --git a/docs/features/configuration.rst b/docs/features/configuration.rst index 8a1e61a1..0306c563 100644 --- a/docs/features/configuration.rst +++ b/docs/features/configuration.rst @@ -1,7 +1,7 @@ Configuration ============ -An example configuration can be found `here `_. +An example configuration can be found `here `_. There are two sections to the configuration. An array of ReRoutes and a GlobalConfiguration. The ReRoutes are the objects that tell Ocelot how to treat an upstream request. The Global configuration is a bit hacky and allows overrides of ReRoute specific settings. It's useful @@ -69,22 +69,6 @@ Here is an example ReRoute configuration, You don't need to set all of these thi More information on how to use these options is below.. -Follow Redirects / Use CookieContainer -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Use HttpHandlerOptions in ReRoute configuration to set up HttpHandler behavior: - -1. AllowAutoRedirect is a value that indicates whether the request should follow redirection responses. Set it true if the request should automatically -follow redirection responses from the Downstream resource; otherwise false. The default value is false. -2. UseCookieContainer is a value that indicates whether the handler uses the CookieContainer -property to store server cookies and uses these cookies when sending requests. The default value is false. Please note -that if you are using the CookieContainer Ocelot caches the HttpClient for each downstream service. This means that all requests -to that DownstreamService will share the same cookies. `Issue 274 `_ was created because a user -noticed that the cookies were being shared. I tried to think of a nice way to handle this but I think it is impossible. If you don't cache the clients -that means each request gets a new client and therefore a new cookie container. If you clear the cookies from the cached client container you get race conditions due to inflight -requests. This would also mean that subsequent requests dont use the cookies from the previous response! All in all not a great situation. I would avoid setting -UseCookieContainer to true unless you have a really really good reason. Just look at your response headers and forward the cookies back with your next request! - Multiple environments ^^^^^^^^^^^^^^^^^^^^^ @@ -99,15 +83,40 @@ to you .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddJsonFile($"configuration.{hostingContext.HostingEnvironment.EnvironmentName}.json") .AddEnvironmentVariables(); }) -Ocelot should now use the environment specific configuration and fall back to configuration.json if there isnt one. +Ocelot will now use the environment specific configuration and fall back to ocelot.json if there isnt one. You also need to set the corresponding environment variable which is ASPNETCORE_ENVIRONMENT. More info on this can be found in the `asp.net core docs `_. +Merging configuration files +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This feature was requested in `Issue 296 `_ and allows users to have multiple configuration files to make managing large configurations easier. + +Instead of adding the configuration directly e.g. AddJsonFile("ocelot.json") you can call AddOcelot() like below. + +.. code-block:: csharp + + .ConfigureAppConfiguration((hostingContext, config) => + { + config + .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", true, true) + .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) + .AddOcelot() + .AddEnvironmentVariables(); + }) + +In this scenario Ocelot will look for any files that match the pattern ocleot.*.json and then merge these together. If you want to set the GlobalConfiguration property you must have a file called ocelot.global.json. + +The way Ocelot merges the files is basically load them, loop over them, add any ReRoutes, add any AggregateReRoutes and if the file is called ocelot.global.json add the GlobalConfiguration aswell as any ReRoutes or AggregateReRoutes. Ocelot will then save the merged configuration to a file called ocelot.json and this will be used as the source of truth while ocelot is running. + +At the moment there is no validation at this stage it only happens when Ocelot validates the final merged configuration. This is something to be aware of when you are investigating problems. I would advise always checking what is in ocelot.json if you have any problems. + Store configuration in consul ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +128,7 @@ If you add the following when you register your services Ocelot will attempt to .AddOcelot() .AddStoreOcelotConfigurationInConsul(); -You also need to add the following to your configuration.json. This is how Ocelot +You also need to add the following to your ocelot.json. This is how Ocelot finds your Consul agent and interacts to load and store the configuration from Consul. .. code-block:: json @@ -135,3 +144,19 @@ I decided to create this feature after working on the raft consensus algorithm a I guess it means if you want to use Ocelot to its fullest you take on Consul as a dependency for now. This feature has a 3 second ttl cache before making a new request to your local consul agent. + +Follow Redirects / Use CookieContainer +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use HttpHandlerOptions in ReRoute configuration to set up HttpHandler behavior: + +1. AllowAutoRedirect is a value that indicates whether the request should follow redirection responses. Set it true if the request should automatically +follow redirection responses from the Downstream resource; otherwise false. The default value is false. +2. UseCookieContainer is a value that indicates whether the handler uses the CookieContainer +property to store server cookies and uses these cookies when sending requests. The default value is false. Please note +that if you are using the CookieContainer Ocelot caches the HttpClient for each downstream service. This means that all requests +to that DownstreamService will share the same cookies. `Issue 274 `_ was created because a user +noticed that the cookies were being shared. I tried to think of a nice way to handle this but I think it is impossible. If you don't cache the clients +that means each request gets a new client and therefore a new cookie container. If you clear the cookies from the cached client container you get race conditions due to inflight +requests. This would also mean that subsequent requests dont use the cookies from the previous response! All in all not a great situation. I would avoid setting +UseCookieContainer to true unless you have a really really good reason. Just look at your response headers and forward the cookies back with your next request! diff --git a/docs/features/delegatinghandlers.rst b/docs/features/delegatinghandlers.rst index 80dfa16b..445a46fb 100644 --- a/docs/features/delegatinghandlers.rst +++ b/docs/features/delegatinghandlers.rst @@ -40,7 +40,7 @@ Or transient as below... .AddTransientDelegatingHandler() Both of these Add methods have a default parameter called global which is set to false. If it is false then the intent of -the DelegatingHandler is to be applied to specific ReRoutes via configuration.json (more on that later). If it is set to true +the DelegatingHandler is to be applied to specific ReRoutes via ocelot.json (more on that later). If it is set to true then it becomes a global handler and will be applied to all ReRoutes. e.g. @@ -58,7 +58,7 @@ Or transient as below... .AddTransientDelegatingHandler(true) Finally if you want ReRoute specific DelegatingHandlers or to order your specific and / or global (more on this later) DelegatingHandlers -then you must add the following json to the specific ReRoute in configuration.json. The names in the array must match the class names of your +then you must add the following json to the specific ReRoute in ocelot.json. The names in the array must match the class names of your DelegatingHandlers for Ocelot to match them together. .. code-block:: json @@ -70,8 +70,8 @@ DelegatingHandlers for Ocelot to match them together. You can have as many DelegatingHandlers as you want and they are run in the following order: -1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from configuration.json. -2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from configuration.json ordered as they are in the DelegatingHandlers array. +1. Any globals that are left in the order they were added to services and are not in the DelegatingHandlers array from ocelot.json. +2. Any non global DelegatingHandlers plus any globals that were in the DelegatingHandlers array from ocelot.json ordered as they are in the DelegatingHandlers array. 3. Tracing DelegatingHandler if enabled (see tracing docs). 4. QoS DelegatingHandler if enabled (see QoS docs). 5. The HttpClient sends the HttpRequestMessage. diff --git a/docs/features/headerstransformation.rst b/docs/features/headerstransformation.rst index 544ae2b0..744227e2 100644 --- a/docs/features/headerstransformation.rst +++ b/docs/features/headerstransformation.rst @@ -8,7 +8,7 @@ Add to Request This feature was requestes in `GitHub #313 `_. -If you want to add a header to your upstream request please add the following to a ReRoute in your configuration.json: +If you want to add a header to your upstream request please add the following to a ReRoute in your ocelot.json: .. code-block:: json @@ -25,7 +25,7 @@ Add to Response This feature was requested in `GitHub #280 `_. -If you want to add a header to your downstream response please add the following to a ReRoute in configuration.json. +If you want to add a header to your downstream response please add the following to a ReRoute in ocelot.json.. .. code-block:: json @@ -57,7 +57,7 @@ The key is "Test" and the value is "http://www.bbc.co.uk/, http://ocelot.com/". Pre Downstream Request ^^^^^^^^^^^^^^^^^^^^^^ -Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This header will be changed before the request downstream and will be sent to the downstream server. +Add the following to a ReRoute in ocelot.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This header will be changed before the request downstream and will be sent to the downstream server. .. code-block:: json @@ -68,7 +68,7 @@ Add the following to a ReRoute in configuration.json in order to replace http:// Post Downstream Request ^^^^^^^^^^^^^^^^^^^^^^^ -Add the following to a ReRoute in configuration.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service. +Add the following to a ReRoute in ocelot.json in order to replace http://www.bbc.co.uk/ with http://ocelot.com/. This transformation will take place after Ocelot has received the response from the downstream service. .. code-block:: json diff --git a/docs/features/loadbalancer.rst b/docs/features/loadbalancer.rst index f587aa22..c2cc0f26 100644 --- a/docs/features/loadbalancer.rst +++ b/docs/features/loadbalancer.rst @@ -16,7 +16,7 @@ You must choose in your configuration which load balancer to use. Configuration ^^^^^^^^^^^^^ -The following shows how to set up multiple downstream services for a ReRoute using configuration.json and then select the LeadConnection load balancer. This is the simplest way to get load balancing set up. +The following shows how to set up multiple downstream services for a ReRoute using ocelot.json and then select the LeadConnection load balancer. This is the simplest way to get load balancing set up. .. code-block:: json diff --git a/docs/features/ratelimiting.rst b/docs/features/ratelimiting.rst index d929c905..7f9c0768 100644 --- a/docs/features/ratelimiting.rst +++ b/docs/features/ratelimiting.rst @@ -23,7 +23,7 @@ Period - This value specifies the period, such as 1s, 5m, 1h,1d and so on. PeriodTimespan - This value specifies that we can retry after a certain number of seconds. Limit - This value specifies the maximum number of requests that a client can make in a defined period. -You can also set the following in the GlobalConfiguration part of configuration.json +You can also set the following in the GlobalConfiguration part of ocelot.json .. code-block:: json diff --git a/docs/features/requestaggregation.rst b/docs/features/requestaggregation.rst index c3c7ad13..a5ca30f6 100644 --- a/docs/features/requestaggregation.rst +++ b/docs/features/requestaggregation.rst @@ -7,7 +7,7 @@ architecture with Ocelot. This feature was requested as part of `Issue 79 `_ and further improvements were made as part of `Issue 298 `_. -In order to set this up you must do something like the following in your configuration.json. Here we have specified two normal ReRoutes and each one has a Key property. +In order to set this up you must do something like the following in your ocelot.json. Here we have specified two normal ReRoutes and each one has a Key property. We then specify an Aggregate that composes the two ReRoutes using their keys in the ReRouteKeys list and says then we have the UpstreamPathTemplate which works like a normal ReRoute. Obviously you cannot have duplicate UpstreamPathTemplates between ReRoutes and Aggregates. You can use all of Ocelot's normal ReRoute options apart from RequestIdKey (explained in gotchas below). @@ -17,7 +17,7 @@ Advanced register your own Aggregators Ocelot started with just the basic request aggregation and since then we have added a more advanced method that let's the user take in the responses from the downstream services and then aggregate them into a response object. -The configuration.json setup is pretty much the same as the basic aggregation approach apart from you need to add an Aggregator property like below. +The ocelot.json setup is pretty much the same as the basic aggregation approach apart from you need to add an Aggregator property like below. .. code-block:: json diff --git a/docs/features/requestid.rst b/docs/features/requestid.rst index 6e4f239b..37752eda 100644 --- a/docs/features/requestid.rst +++ b/docs/features/requestid.rst @@ -12,7 +12,7 @@ In order to use the reques tid feature you have two options. *Global* -In your configuration.json set the following in the GlobalConfiguration section. This will be used for all requests into Ocelot. +In your ocelot.json set the following in the GlobalConfiguration section. This will be used for all requests into Ocelot. .. code-block:: json @@ -24,7 +24,7 @@ I reccomend using the GlobalConfiguration unless you really need it to be ReRout *ReRoute* -If you want to override this for a specific ReRoute add the following to configuration.json for the specific ReRoute. +If you want to override this for a specific ReRoute add the following to ocelot.json for the specific ReRoute. .. code-block:: json diff --git a/docs/features/routing.rst b/docs/features/routing.rst index b414d6c5..664021a6 100644 --- a/docs/features/routing.rst +++ b/docs/features/routing.rst @@ -145,9 +145,9 @@ Priority ^^^^^^^^ In `Issue 270 `_ I finally decided to expose the ReRoute priority in -configuration.json. This means you can decide in what order you want your ReRoutes to match the Upstream HttpRequest. +ocelot.json. This means you can decide in what order you want your ReRoutes to match the Upstream HttpRequest. -In order to get this working add the following to a ReRoute in configuration.json, 0 is just an example value here but will explain below. +In order to get this working add the following to a ReRoute in ocelot.json, 0 is just an example value here but will explain below. .. code-block:: json diff --git a/docs/features/tracing.rst b/docs/features/tracing.rst index 0a896d45..aa4b1fd3 100644 --- a/docs/features/tracing.rst +++ b/docs/features/tracing.rst @@ -20,7 +20,7 @@ In your ConfigureServices method option.Service = "Ocelot"; }); -Then in your configuration.json add the following to the ReRoute you want to trace.. +Then in your ocelot.json add the following to the ReRoute you want to trace.. .. code-block:: json diff --git a/docs/features/websockets.rst b/docs/features/websockets.rst index 828d1051..624f42a9 100644 --- a/docs/features/websockets.rst +++ b/docs/features/websockets.rst @@ -15,7 +15,7 @@ In your Configure method you need to tell your application to use WebSockets. app.UseOcelot().Wait(); }) -Then in your configuration.json add the following to proxy a ReRoute using websockets. +Then in your ocelot.json add the following to proxy a ReRoute using websockets. .. code-block:: json diff --git a/docs/introduction/gettingstarted.rst b/docs/introduction/gettingstarted.rst index 7f81cb51..0c11f40d 100644 --- a/docs/introduction/gettingstarted.rst +++ b/docs/introduction/gettingstarted.rst @@ -18,7 +18,7 @@ All versions can be found `here `_. **Configuration** -The following is a very basic configuration.json. It won't do anything but should get Ocelot starting. +The following is a very basic ocelot.json. It won't do anything but should get Ocelot starting. .. code-block:: json @@ -55,7 +55,7 @@ AddOcelot() (adds ocelot services), UseOcelot().Wait() (sets up all the Ocelot m .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); }) .ConfigureServices(s => { @@ -87,7 +87,7 @@ All versions can be found `here `_. **Configuration** -The following is a very basic configuration.json. It won't do anything but should get Ocelot starting. +The following is a very basic ocelot.json. It won't do anything but should get Ocelot starting. .. code-block:: json @@ -135,7 +135,7 @@ An example startup using a json file for configuration can be seen below. .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); Configuration = builder.Build(); diff --git a/docs/introduction/notsupported.rst b/docs/introduction/notsupported.rst index 37e5b5eb..e578bca2 100644 --- a/docs/introduction/notsupported.rst +++ b/docs/introduction/notsupported.rst @@ -7,7 +7,7 @@ Ocelot does not support... * Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :( -* Swagger - I have looked multiple times at building swagger.json out of the Ocelot configuration.json but it doesnt fit into the vision +* Swagger - I have looked multiple times at building swagger.json out of the Ocelot ocelot.json but it doesnt fit into the vision I have for Ocelot. If you would like to have Swagger in Ocelot then you must roll your own swagger.json and do the following in your Startup.cs or Program.cs. The code sample below registers a piece of middleware that loads your hand rolled swagger.json and returns it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from Swashbuckle.AspNetCore @@ -28,8 +28,8 @@ it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from app.UseOcelot().Wait(); -The main reasons why I don't think Swagger makes sense is we already hand roll our definition in configuration.json. -If we want people developing against Ocelot to be able to see what routes are available then either share the configuration.json +The main reasons why I don't think Swagger makes sense is we already hand roll our definition in ocelot.json. +If we want people developing against Ocelot to be able to see what routes are available then either share the ocelot.json with them (This should be as easy as granting access to a repo etc) or use the Ocelot administration API so that they can query Ocelot for the configuration. In addition to this many people will configure Ocelot to proxy all traffic like /products/{everything} to there product service @@ -40,4 +40,4 @@ package doesnt reload swagger.json if it changes during runtime. Ocelot's config information would not match. Unless I rolled my own Swagger implementation. If the user wants something to easily test against the Ocelot API then I suggest using Postman as a simple way to do this. It might -even be possible to write something that maps configuration.json to the postman json spec. However I don't intend to do this. \ No newline at end of file +even be possible to write something that maps ocelot.json to the postman json spec. However I don't intend to do this. \ No newline at end of file diff --git a/samples/OcelotGraphQL/OcelotGraphQL.csproj b/samples/OcelotGraphQL/OcelotGraphQL.csproj index 2f29e395..ec015d1b 100644 --- a/samples/OcelotGraphQL/OcelotGraphQL.csproj +++ b/samples/OcelotGraphQL/OcelotGraphQL.csproj @@ -3,7 +3,7 @@ netcoreapp2.0 - + PreserveNewest diff --git a/samples/OcelotGraphQL/Program.cs b/samples/OcelotGraphQL/Program.cs index 94e1295b..81938f9c 100644 --- a/samples/OcelotGraphQL/Program.cs +++ b/samples/OcelotGraphQL/Program.cs @@ -106,7 +106,7 @@ namespace OcelotGraphQL .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); }) .ConfigureServices(s => { diff --git a/samples/OcelotGraphQL/README.md b/samples/OcelotGraphQL/README.md index 06ec668a..b2101d56 100644 --- a/samples/OcelotGraphQL/README.md +++ b/samples/OcelotGraphQL/README.md @@ -47,7 +47,7 @@ RESPONSE ## Notes -Please note this project never goes out to another service, it just gets the data for GraphQL in memory. You would need to add the details of your GraphQL server in configuration.json e.g. +Please note this project never goes out to another service, it just gets the data for GraphQL in memory. You would need to add the details of your GraphQL server in ocelot.json e.g. ```json { diff --git a/samples/OcelotGraphQL/configuration.json b/samples/OcelotGraphQL/ocelot.json similarity index 100% rename from samples/OcelotGraphQL/configuration.json rename to samples/OcelotGraphQL/ocelot.json diff --git a/samples/OcelotServiceFabric/.gitignore b/samples/OcelotServiceFabric/.gitignore index 733dbb07..84aa4b08 100644 --- a/samples/OcelotServiceFabric/.gitignore +++ b/samples/OcelotServiceFabric/.gitignore @@ -13,7 +13,7 @@ # Service fabric OcelotApplicationApiGatewayPkg/Code OcelotApplication/OcelotApplicationApiGatewayPkg/Code/appsettings.json -OcelotApplication/OcelotApplicationApiGatewayPkg/Code/configuration.json +OcelotApplication/OcelotApplicationApiGatewayPkg/Code/ocelot.json OcelotApplication/OcelotApplicationApiGatewayPkg/Code/runtimes/ OcelotApplicationServicePkg/Code OcelotApplication/OcelotApplicationApiGatewayPkg/Code/web.config diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj index 1ff69c09..08324cbe 100644 --- a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/OcelotApplicationApiGateway.csproj @@ -8,7 +8,7 @@ OcelotApplicationApiGateway - + PreserveNewest diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs index 6685e11f..7d913cfa 100644 --- a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs +++ b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/WebCommunicationListener.cs @@ -67,7 +67,7 @@ namespace OcelotApplicationApiGateway .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); }) .ConfigureLogging((hostingContext, logging) => diff --git a/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json b/samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ocelot.json similarity index 100% rename from samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/configuration.json rename to samples/OcelotServiceFabric/src/OcelotApplicationApiGateway/ocelot.json diff --git a/src/Ocelot/Cache/OutputCacheController.cs b/src/Ocelot/Cache/OutputCacheController.cs index 32b9fa7c..cc33e8aa 100644 --- a/src/Ocelot/Cache/OutputCacheController.cs +++ b/src/Ocelot/Cache/OutputCacheController.cs @@ -1,9 +1,5 @@ -using System.Net.Http; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Ocelot.Cache; -using Ocelot.Configuration.Provider; namespace Ocelot.Cache { @@ -11,7 +7,7 @@ namespace Ocelot.Cache [Route("outputcache")] public class OutputCacheController : Controller { - private IOcelotCache _cache; + private readonly IOcelotCache _cache; public OutputCacheController(IOcelotCache cache) { @@ -26,4 +22,4 @@ namespace Ocelot.Cache return new NoContentResult(); } } -} \ No newline at end of file +} diff --git a/src/Ocelot/Configuration/Authentication/HashMatcher.cs b/src/Ocelot/Configuration/Authentication/HashMatcher.cs deleted file mode 100644 index 5f17362f..00000000 --- a/src/Ocelot/Configuration/Authentication/HashMatcher.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using Microsoft.AspNetCore.Cryptography.KeyDerivation; - -namespace Ocelot.Configuration.Authentication -{ - public class HashMatcher : IHashMatcher - { - public bool Match(string password, string salt, string hash) - { - byte[] s = Convert.FromBase64String(salt); - - string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2( - password: password, - salt: s, - prf: KeyDerivationPrf.HMACSHA256, - iterationCount: 10000, - numBytesRequested: 256 / 8)); - - return hashed == hash; - } - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Authentication/IHashMatcher.cs b/src/Ocelot/Configuration/Authentication/IHashMatcher.cs deleted file mode 100644 index 629bf008..00000000 --- a/src/Ocelot/Configuration/Authentication/IHashMatcher.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ocelot.Configuration.Authentication -{ - public interface IHashMatcher - { - bool Match(string password, string salt, string hash); - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/FileInternalConfigurationCreator.cs similarity index 90% rename from src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs rename to src/Ocelot/Configuration/Creator/FileInternalConfigurationCreator.cs index cee03813..c14e4aab 100644 --- a/src/Ocelot/Configuration/Creator/FileOcelotConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/FileInternalConfigurationCreator.cs @@ -16,9 +16,8 @@ namespace Ocelot.Configuration.Creator /// /// Register as singleton /// - public class FileOcelotConfigurationCreator : IOcelotConfigurationCreator + public class FileInternalConfigurationCreator : IInternalConfigurationCreator { - private readonly IOptions _options; private readonly IConfigurationValidator _configurationValidator; private readonly IOcelotLogger _logger; private readonly IClaimsToThingCreator _claimsToThingCreator; @@ -35,8 +34,7 @@ namespace Ocelot.Configuration.Creator private readonly IHeaderFindAndReplaceCreator _headerFAndRCreator; private readonly IDownstreamAddressesCreator _downstreamAddressesCreator; - public FileOcelotConfigurationCreator( - IOptions options, + public FileInternalConfigurationCreator( IConfigurationValidator configurationValidator, IOcelotLoggerFactory loggerFactory, IClaimsToThingCreator claimsToThingCreator, @@ -62,9 +60,8 @@ namespace Ocelot.Configuration.Creator _requestIdKeyCreator = requestIdKeyCreator; _upstreamTemplatePatternCreator = upstreamTemplatePatternCreator; _authOptionsCreator = authOptionsCreator; - _options = options; _configurationValidator = configurationValidator; - _logger = loggerFactory.CreateLogger(); + _logger = loggerFactory.CreateLogger(); _claimsToThingCreator = claimsToThingCreator; _serviceProviderConfigCreator = serviceProviderConfigCreator; _qosOptionsCreator = qosOptionsCreator; @@ -72,19 +69,19 @@ namespace Ocelot.Configuration.Creator _httpHandlerOptionsCreator = httpHandlerOptionsCreator; } - public async Task> Create(FileConfiguration fileConfiguration) + public async Task> Create(FileConfiguration fileConfiguration) { var config = await SetUpConfiguration(fileConfiguration); return config; } - private async Task> SetUpConfiguration(FileConfiguration fileConfiguration) + private async Task> SetUpConfiguration(FileConfiguration fileConfiguration) { var response = await _configurationValidator.IsValid(fileConfiguration); if (response.Data.IsError) { - return new ErrorResponse(response.Data.Errors); + return new ErrorResponse(response.Data.Errors); } var reRoutes = new List(); @@ -106,9 +103,9 @@ namespace Ocelot.Configuration.Creator var serviceProviderConfiguration = _serviceProviderConfigCreator.Create(fileConfiguration.GlobalConfiguration); - var config = new OcelotConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey); + var config = new InternalConfiguration(reRoutes, _adminPath.Path, serviceProviderConfiguration, fileConfiguration.GlobalConfiguration.RequestIdKey); - return new OkResponse(config); + return new OkResponse(config); } public ReRoute SetUpAggregateReRoute(List reRoutes, FileAggregateReRoute aggregateReRoute, FileGlobalConfiguration globalConfiguration) @@ -214,7 +211,7 @@ namespace Ocelot.Configuration.Creator .WithDownstreamHeaderFindAndReplace(hAndRs.Downstream) .WithUpstreamHost(fileReRoute.UpstreamHost) .WithDelegatingHandlers(fileReRoute.DelegatingHandlers) - .WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream) + .WithAddHeadersToDownstream(hAndRs.AddHeadersToDownstream) .WithAddHeadersToUpstream(hAndRs.AddHeadersToUpstream) .Build(); diff --git a/src/Ocelot/Configuration/Creator/IInternalConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/IInternalConfigurationCreator.cs new file mode 100644 index 00000000..a0f3cb42 --- /dev/null +++ b/src/Ocelot/Configuration/Creator/IInternalConfigurationCreator.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Ocelot.Configuration.File; +using Ocelot.Responses; + +namespace Ocelot.Configuration.Creator +{ + public interface IInternalConfigurationCreator + { + Task> Create(FileConfiguration fileConfiguration); + } +} diff --git a/src/Ocelot/Configuration/Creator/IOcelotConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/IOcelotConfigurationCreator.cs deleted file mode 100644 index 4b431701..00000000 --- a/src/Ocelot/Configuration/Creator/IOcelotConfigurationCreator.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.File; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Creator -{ - public interface IOcelotConfigurationCreator - { - Task> Create(FileConfiguration fileConfiguration); - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs b/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs index 5e7fcd37..8569001e 100644 --- a/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs +++ b/src/Ocelot/Configuration/Creator/IdentityServerConfigurationCreator.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using IdentityServer4.AccessTokenValidation; -using IdentityServer4.Models; -using Ocelot.Configuration.Provider; namespace Ocelot.Configuration.Creator { diff --git a/src/Ocelot/Configuration/FileConfigurationController.cs b/src/Ocelot/Configuration/FileConfigurationController.cs index 7bdf4926..707eb61d 100644 --- a/src/Ocelot/Configuration/FileConfigurationController.cs +++ b/src/Ocelot/Configuration/FileConfigurationController.cs @@ -2,34 +2,34 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; using Ocelot.Configuration.File; -using Ocelot.Configuration.Provider; using Ocelot.Configuration.Setter; using Ocelot.Raft; using Rafty.Concensus; namespace Ocelot.Configuration { + using Repository; + [Authorize] [Route("configuration")] public class FileConfigurationController : Controller { - private readonly IFileConfigurationProvider _configGetter; - private readonly IFileConfigurationSetter _configSetter; - private readonly IServiceProvider _serviceProvider; + private readonly IFileConfigurationRepository _repo; + private readonly IFileConfigurationSetter _setter; + private readonly IServiceProvider _provider; - public FileConfigurationController(IFileConfigurationProvider getFileConfig, IFileConfigurationSetter configSetter, IServiceProvider serviceProvider) + public FileConfigurationController(IFileConfigurationRepository repo, IFileConfigurationSetter setter, IServiceProvider provider) { - _configGetter = getFileConfig; - _configSetter = configSetter; - _serviceProvider = serviceProvider; + _repo = repo; + _setter = setter; + _provider = provider; } [HttpGet] public async Task Get() { - var response = await _configGetter.Get(); + var response = await _repo.Get(); if(response.IsError) { @@ -43,7 +43,7 @@ namespace Ocelot.Configuration public async Task Post([FromBody]FileConfiguration fileConfiguration) { //todo - this code is a bit shit sort it out.. - var test = _serviceProvider.GetService(typeof(INode)); + var test = _provider.GetService(typeof(INode)); if (test != null) { var node = (INode)test; @@ -56,7 +56,7 @@ namespace Ocelot.Configuration return new OkObjectResult(result.Command.Configuration); } - var response = await _configSetter.Set(fileConfiguration); + var response = await _setter.Set(fileConfiguration); if (response.IsError) { diff --git a/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs b/src/Ocelot/Configuration/IIdentityServerConfiguration.cs similarity index 67% rename from src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs rename to src/Ocelot/Configuration/IIdentityServerConfiguration.cs index 8a76eb9f..0eb70347 100644 --- a/src/Ocelot/Configuration/Provider/IIdentityServerConfiguration.cs +++ b/src/Ocelot/Configuration/IIdentityServerConfiguration.cs @@ -1,16 +1,14 @@ -using System.Collections.Generic; -using IdentityServer4.AccessTokenValidation; -using IdentityServer4.Models; - -namespace Ocelot.Configuration.Provider -{ - public interface IIdentityServerConfiguration - { - string ApiName { get; } - string ApiSecret { get; } - bool RequireHttps { get; } - List AllowedScopes { get; } - string CredentialsSigningCertificateLocation { get; } - string CredentialsSigningCertificatePassword { get; } - } -} \ No newline at end of file +namespace Ocelot.Configuration +{ + using System.Collections.Generic; + + public interface IIdentityServerConfiguration + { + string ApiName { get; } + string ApiSecret { get; } + bool RequireHttps { get; } + List AllowedScopes { get; } + string CredentialsSigningCertificateLocation { get; } + string CredentialsSigningCertificatePassword { get; } + } +} diff --git a/src/Ocelot/Configuration/IOcelotConfiguration.cs b/src/Ocelot/Configuration/IInternalConfiguration.cs similarity index 83% rename from src/Ocelot/Configuration/IOcelotConfiguration.cs rename to src/Ocelot/Configuration/IInternalConfiguration.cs index 2353cb85..c1781c48 100644 --- a/src/Ocelot/Configuration/IOcelotConfiguration.cs +++ b/src/Ocelot/Configuration/IInternalConfiguration.cs @@ -1,12 +1,12 @@ -using System.Collections.Generic; - -namespace Ocelot.Configuration -{ - public interface IOcelotConfiguration - { - List ReRoutes { get; } - string AdministrationPath {get;} - ServiceProviderConfiguration ServiceProviderConfiguration {get;} - string RequestId {get;} - } -} +using System.Collections.Generic; + +namespace Ocelot.Configuration +{ + public interface IInternalConfiguration + { + List ReRoutes { get; } + string AdministrationPath {get;} + ServiceProviderConfiguration ServiceProviderConfiguration {get;} + string RequestId {get;} + } +} diff --git a/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs b/src/Ocelot/Configuration/IdentityServerConfiguration.cs similarity index 66% rename from src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs rename to src/Ocelot/Configuration/IdentityServerConfiguration.cs index 795e6994..b8b00ea2 100644 --- a/src/Ocelot/Configuration/Provider/IdentityServerConfiguration.cs +++ b/src/Ocelot/Configuration/IdentityServerConfiguration.cs @@ -1,32 +1,30 @@ -using System.Collections.Generic; -using IdentityServer4.AccessTokenValidation; -using IdentityServer4.Models; - -namespace Ocelot.Configuration.Provider -{ - public class IdentityServerConfiguration : IIdentityServerConfiguration - { - public IdentityServerConfiguration( - string apiName, - bool requireHttps, - string apiSecret, - List allowedScopes, - string credentialsSigningCertificateLocation, - string credentialsSigningCertificatePassword) - { - ApiName = apiName; - RequireHttps = requireHttps; - ApiSecret = apiSecret; - AllowedScopes = allowedScopes; - CredentialsSigningCertificateLocation = credentialsSigningCertificateLocation; - CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword; - } - - public string ApiName { get; private set; } - public bool RequireHttps { get; private set; } - public List AllowedScopes { get; private set; } - public string ApiSecret { get; private set; } - public string CredentialsSigningCertificateLocation { get; private set; } - public string CredentialsSigningCertificatePassword { get; private set; } - } -} \ No newline at end of file +namespace Ocelot.Configuration +{ + using System.Collections.Generic; + + public class IdentityServerConfiguration : IIdentityServerConfiguration + { + public IdentityServerConfiguration( + string apiName, + bool requireHttps, + string apiSecret, + List allowedScopes, + string credentialsSigningCertificateLocation, + string credentialsSigningCertificatePassword) + { + ApiName = apiName; + RequireHttps = requireHttps; + ApiSecret = apiSecret; + AllowedScopes = allowedScopes; + CredentialsSigningCertificateLocation = credentialsSigningCertificateLocation; + CredentialsSigningCertificatePassword = credentialsSigningCertificatePassword; + } + + public string ApiName { get; } + public bool RequireHttps { get; } + public List AllowedScopes { get; } + public string ApiSecret { get; } + public string CredentialsSigningCertificateLocation { get; } + public string CredentialsSigningCertificatePassword { get; } + } +} diff --git a/src/Ocelot/Configuration/OcelotConfiguration.cs b/src/Ocelot/Configuration/InternalConfiguration.cs similarity index 67% rename from src/Ocelot/Configuration/OcelotConfiguration.cs rename to src/Ocelot/Configuration/InternalConfiguration.cs index 1ab73b87..429bb9c0 100644 --- a/src/Ocelot/Configuration/OcelotConfiguration.cs +++ b/src/Ocelot/Configuration/InternalConfiguration.cs @@ -1,20 +1,20 @@ -using System.Collections.Generic; - -namespace Ocelot.Configuration -{ - public class OcelotConfiguration : IOcelotConfiguration - { - public OcelotConfiguration(List reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId) - { - ReRoutes = reRoutes; - AdministrationPath = administrationPath; - ServiceProviderConfiguration = serviceProviderConfiguration; - RequestId = requestId; - } - - public List ReRoutes { get; } - public string AdministrationPath {get;} - public ServiceProviderConfiguration ServiceProviderConfiguration {get;} - public string RequestId {get;} - } -} +using System.Collections.Generic; + +namespace Ocelot.Configuration +{ + public class InternalConfiguration : IInternalConfiguration + { + public InternalConfiguration(List reRoutes, string administrationPath, ServiceProviderConfiguration serviceProviderConfiguration, string requestId) + { + ReRoutes = reRoutes; + AdministrationPath = administrationPath; + ServiceProviderConfiguration = serviceProviderConfiguration; + RequestId = requestId; + } + + public List ReRoutes { get; } + public string AdministrationPath {get;} + public ServiceProviderConfiguration ServiceProviderConfiguration {get;} + public string RequestId {get;} + } +} diff --git a/src/Ocelot/Configuration/Provider/FileConfigurationProvider.cs b/src/Ocelot/Configuration/Provider/FileConfigurationProvider.cs deleted file mode 100644 index fdcd949b..00000000 --- a/src/Ocelot/Configuration/Provider/FileConfigurationProvider.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Ocelot.Configuration.File; -using Ocelot.Configuration.Repository; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Provider -{ - public class FileConfigurationProvider : IFileConfigurationProvider - { - private IFileConfigurationRepository _repo; - - public FileConfigurationProvider(IFileConfigurationRepository repo) - { - _repo = repo; - } - - public async Task> Get() - { - var fileConfig = await _repo.Get(); - return new OkResponse(fileConfig.Data); - } - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Provider/IFileConfigurationProvider.cs b/src/Ocelot/Configuration/Provider/IFileConfigurationProvider.cs deleted file mode 100644 index c2ab51cb..00000000 --- a/src/Ocelot/Configuration/Provider/IFileConfigurationProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.File; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Provider -{ - public interface IFileConfigurationProvider - { - Task> Get(); - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Provider/IOcelotConfigurationProvider.cs b/src/Ocelot/Configuration/Provider/IOcelotConfigurationProvider.cs deleted file mode 100644 index 80f4583b..00000000 --- a/src/Ocelot/Configuration/Provider/IOcelotConfigurationProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.File; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Provider -{ - public interface IOcelotConfigurationProvider - { - Task> Get(); - } -} diff --git a/src/Ocelot/Configuration/Provider/OcelotConfigurationProvider.cs b/src/Ocelot/Configuration/Provider/OcelotConfigurationProvider.cs deleted file mode 100644 index ed72a60e..00000000 --- a/src/Ocelot/Configuration/Provider/OcelotConfigurationProvider.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.File; -using Ocelot.Configuration.Repository; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Provider -{ - /// - /// Register as singleton - /// - public class OcelotConfigurationProvider : IOcelotConfigurationProvider - { - private readonly IOcelotConfigurationRepository _config; - - public OcelotConfigurationProvider(IOcelotConfigurationRepository repo) - { - _config = repo; - } - - public async Task> Get() - { - var repoConfig = await _config.Get(); - - if (repoConfig.IsError) - { - return new ErrorResponse(repoConfig.Errors); - } - - return new OkResponse(repoConfig.Data); - } - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs index 7db04a09..21216168 100644 --- a/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs +++ b/src/Ocelot/Configuration/Repository/ConsulFileConfigurationRepository.cs @@ -1,30 +1,47 @@ -using System; -using System.Text; -using System.Threading.Tasks; -using Consul; -using Newtonsoft.Json; -using Ocelot.Configuration.File; -using Ocelot.Infrastructure.Consul; -using Ocelot.Responses; -using Ocelot.ServiceDiscovery.Configuration; - namespace Ocelot.Configuration.Repository { + using System; + using System.Text; + using System.Threading.Tasks; + using Consul; + using Newtonsoft.Json; + using Ocelot.Configuration.File; + using Ocelot.Infrastructure.Consul; + using Ocelot.Logging; + using Ocelot.Responses; + using Ocelot.ServiceDiscovery.Configuration; + public class ConsulFileConfigurationRepository : IFileConfigurationRepository { private readonly ConsulClient _consul; - private const string OcelotConfiguration = "OcelotConfiguration"; + private const string OcelotConfiguration = "InternalConfiguration"; private readonly Cache.IOcelotCache _cache; + private readonly IOcelotLogger _logger; public ConsulFileConfigurationRepository( - Cache.IOcelotCache cache, - ServiceProviderConfiguration serviceProviderConfig, - IConsulClientFactory factory) + Cache.IOcelotCache cache, + IInternalConfigurationRepository repo, + IConsulClientFactory factory, + IOcelotLoggerFactory loggerFactory) { - var consulHost = string.IsNullOrEmpty(serviceProviderConfig?.Host) ? "localhost" : serviceProviderConfig?.Host; - var consulPort = serviceProviderConfig?.Port ?? 8500; - var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, serviceProviderConfig?.Token); + _logger = loggerFactory.CreateLogger(); _cache = cache; + + var internalConfig = repo.Get(); + + var consulHost = "localhost"; + var consulPort = 8500; + string token = null; + + if (!internalConfig.IsError) + { + consulHost = string.IsNullOrEmpty(internalConfig.Data.ServiceProviderConfiguration?.Host) ? consulHost : internalConfig.Data.ServiceProviderConfiguration?.Host; + consulPort = internalConfig.Data.ServiceProviderConfiguration?.Port ?? consulPort; + token = internalConfig.Data.ServiceProviderConfiguration?.Token; + } + + var config = new ConsulRegistryConfiguration(consulHost, consulPort, OcelotConfiguration, token); + _consul = factory.Get(config); } diff --git a/src/Ocelot/Configuration/Repository/FileConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/DiskFileConfigurationRepository.cs similarity index 75% rename from src/Ocelot/Configuration/Repository/FileConfigurationRepository.cs rename to src/Ocelot/Configuration/Repository/DiskFileConfigurationRepository.cs index ff5e3876..5fb871f4 100644 --- a/src/Ocelot/Configuration/Repository/FileConfigurationRepository.cs +++ b/src/Ocelot/Configuration/Repository/DiskFileConfigurationRepository.cs @@ -1,52 +1,54 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; -using Newtonsoft.Json; -using Ocelot.Configuration.File; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Repository -{ - public class FileConfigurationRepository : IFileConfigurationRepository - { - private readonly string _configFilePath; - - private static readonly object _lock = new object(); - - public FileConfigurationRepository(IHostingEnvironment hostingEnvironment) - { - _configFilePath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json"; - } - - public Task> Get() - { - string jsonConfiguration; - - lock(_lock) - { - jsonConfiguration = System.IO.File.ReadAllText(_configFilePath); - } - - var fileConfiguration = JsonConvert.DeserializeObject(jsonConfiguration); - - return Task.FromResult>(new OkResponse(fileConfiguration)); - } - - public Task Set(FileConfiguration fileConfiguration) - { - string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); - - lock(_lock) - { - if (System.IO.File.Exists(_configFilePath)) - { - System.IO.File.Delete(_configFilePath); - } - - System.IO.File.WriteAllText(_configFilePath, jsonConfiguration); - } - - return Task.FromResult(new OkResponse()); - } - } -} +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Newtonsoft.Json; +using Ocelot.Configuration.File; +using Ocelot.Responses; + +namespace Ocelot.Configuration.Repository +{ + public class DiskFileConfigurationRepository : IFileConfigurationRepository + { + private readonly string _configFilePath; + + private static readonly object _lock = new object(); + + private const string ConfigurationFileName = "ocelot"; + + public DiskFileConfigurationRepository(IHostingEnvironment hostingEnvironment) + { + _configFilePath = $"{AppContext.BaseDirectory}/{ConfigurationFileName}{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json"; + } + + public Task> Get() + { + string jsonConfiguration; + + lock(_lock) + { + jsonConfiguration = System.IO.File.ReadAllText(_configFilePath); + } + + var fileConfiguration = JsonConvert.DeserializeObject(jsonConfiguration); + + return Task.FromResult>(new OkResponse(fileConfiguration)); + } + + public Task Set(FileConfiguration fileConfiguration) + { + string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); + + lock(_lock) + { + if (System.IO.File.Exists(_configFilePath)) + { + System.IO.File.Delete(_configFilePath); + } + + System.IO.File.WriteAllText(_configFilePath, jsonConfiguration); + } + + return Task.FromResult(new OkResponse()); + } + } +} diff --git a/src/Ocelot/Configuration/Repository/IInternalConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/IInternalConfigurationRepository.cs new file mode 100644 index 00000000..5db4adb5 --- /dev/null +++ b/src/Ocelot/Configuration/Repository/IInternalConfigurationRepository.cs @@ -0,0 +1,10 @@ +using Ocelot.Responses; + +namespace Ocelot.Configuration.Repository +{ + public interface IInternalConfigurationRepository + { + Response Get(); + Response AddOrReplace(IInternalConfiguration internalConfiguration); + } +} diff --git a/src/Ocelot/Configuration/Repository/IOcelotConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/IOcelotConfigurationRepository.cs deleted file mode 100644 index 16b386a1..00000000 --- a/src/Ocelot/Configuration/Repository/IOcelotConfigurationRepository.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.File; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Repository -{ - public interface IOcelotConfigurationRepository - { - Task> Get(); - Task AddOrReplace(IOcelotConfiguration ocelotConfiguration); - } -} \ No newline at end of file diff --git a/src/Ocelot/Configuration/Repository/InMemoryInternalConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/InMemoryInternalConfigurationRepository.cs new file mode 100644 index 00000000..2ac954e3 --- /dev/null +++ b/src/Ocelot/Configuration/Repository/InMemoryInternalConfigurationRepository.cs @@ -0,0 +1,29 @@ +using Ocelot.Responses; + +namespace Ocelot.Configuration.Repository +{ + /// + /// Register as singleton + /// + public class InMemoryInternalConfigurationRepository : IInternalConfigurationRepository + { + private static readonly object LockObject = new object(); + + private IInternalConfiguration _internalConfiguration; + + public Response Get() + { + return new OkResponse(_internalConfiguration); + } + + public Response AddOrReplace(IInternalConfiguration internalConfiguration) + { + lock (LockObject) + { + _internalConfiguration = internalConfiguration; + } + + return new OkResponse(); + } + } +} diff --git a/src/Ocelot/Configuration/Repository/InMemoryOcelotConfigurationRepository.cs b/src/Ocelot/Configuration/Repository/InMemoryOcelotConfigurationRepository.cs deleted file mode 100644 index 9ce50ba6..00000000 --- a/src/Ocelot/Configuration/Repository/InMemoryOcelotConfigurationRepository.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Threading.Tasks; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Repository -{ - /// - /// Register as singleton - /// - public class InMemoryOcelotConfigurationRepository : IOcelotConfigurationRepository - { - private static readonly object LockObject = new object(); - - private IOcelotConfiguration _ocelotConfiguration; - - public Task> Get() - { - return Task.FromResult>(new OkResponse(_ocelotConfiguration)); - } - - public Task AddOrReplace(IOcelotConfiguration ocelotConfiguration) - { - lock (LockObject) - { - _ocelotConfiguration = ocelotConfiguration; - } - - return Task.FromResult(new OkResponse()); - } - } -} diff --git a/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs b/src/Ocelot/Configuration/Setter/FileAndInternalConfigurationSetter.cs similarity index 63% rename from src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs rename to src/Ocelot/Configuration/Setter/FileAndInternalConfigurationSetter.cs index 38a7c1cb..6821553e 100644 --- a/src/Ocelot/Configuration/Setter/FileConfigurationSetter.cs +++ b/src/Ocelot/Configuration/Setter/FileAndInternalConfigurationSetter.cs @@ -1,42 +1,44 @@ -using System.Threading.Tasks; -using Ocelot.Configuration.Creator; -using Ocelot.Configuration.File; -using Ocelot.Configuration.Repository; -using Ocelot.Responses; - -namespace Ocelot.Configuration.Setter -{ - public class FileConfigurationSetter : IFileConfigurationSetter - { - private readonly IOcelotConfigurationRepository _configRepo; - private readonly IOcelotConfigurationCreator _configCreator; - private readonly IFileConfigurationRepository _repo; - - public FileConfigurationSetter(IOcelotConfigurationRepository configRepo, - IOcelotConfigurationCreator configCreator, IFileConfigurationRepository repo) - { - _configRepo = configRepo; - _configCreator = configCreator; - _repo = repo; - } - - public async Task Set(FileConfiguration fileConfig) - { - var response = await _repo.Set(fileConfig); - - if(response.IsError) - { - return new ErrorResponse(response.Errors); - } - - var config = await _configCreator.Create(fileConfig); - - if(!config.IsError) - { - await _configRepo.AddOrReplace(config.Data); - } - - return new ErrorResponse(config.Errors); - } - } -} +using System.Threading.Tasks; +using Ocelot.Configuration.Creator; +using Ocelot.Configuration.File; +using Ocelot.Configuration.Repository; +using Ocelot.Responses; + +namespace Ocelot.Configuration.Setter +{ + public class FileAndInternalConfigurationSetter : IFileConfigurationSetter + { + private readonly IInternalConfigurationRepository _configRepo; + private readonly IInternalConfigurationCreator _configCreator; + private readonly IFileConfigurationRepository _repo; + + public FileAndInternalConfigurationSetter( + IInternalConfigurationRepository configRepo, + IInternalConfigurationCreator configCreator, + IFileConfigurationRepository repo) + { + _configRepo = configRepo; + _configCreator = configCreator; + _repo = repo; + } + + public async Task Set(FileConfiguration fileConfig) + { + var response = await _repo.Set(fileConfig); + + if(response.IsError) + { + return new ErrorResponse(response.Errors); + } + + var config = await _configCreator.Create(fileConfig); + + if(!config.IsError) + { + _configRepo.AddOrReplace(config.Data); + } + + return new ErrorResponse(config.Errors); + } + } +} diff --git a/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs b/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs index 56360ad5..00cb0578 100644 --- a/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs +++ b/src/Ocelot/DependencyInjection/ConfigurationBuilderExtensions.cs @@ -1,21 +1,73 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Configuration.Memory; - namespace Ocelot.DependencyInjection { + using System; + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Configuration.Memory; + using System.IO; + using System.Linq; + using System.Text.RegularExpressions; + using Configuration.File; + using Newtonsoft.Json; + public static class ConfigurationBuilderExtensions { - [Obsolete("Please set BaseUrl in configuration.json GlobalConfiguration.BaseUrl")] + [Obsolete("Please set BaseUrl in ocelot.json GlobalConfiguration.BaseUrl")] public static IConfigurationBuilder AddOcelotBaseUrl(this IConfigurationBuilder builder, string baseUrl) { - var memorySource = new MemoryConfigurationSource(); - memorySource.InitialData = new List> + var memorySource = new MemoryConfigurationSource { - new KeyValuePair("BaseUrl", baseUrl) + InitialData = new List> + { + new KeyValuePair("BaseUrl", baseUrl) + } }; + builder.Add(memorySource); + + return builder; + } + + public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder) + { + const string pattern = "(?i)ocelot(.*).json$"; + + var reg = new Regex(pattern); + + var files = Directory.GetFiles(".") + .Where(path => reg.IsMatch(path)).Where(x => x.Count(s => s == '.') == 3) + .ToList(); + + var fileConfiguration = new FileConfiguration(); + + foreach (var file in files) + { + // windows and unix sigh... + if(files.Count > 1 && (file == "./ocelot.json" || file == ".\\ocelot.json")) + { + continue; + } + + var lines = File.ReadAllText(file); + + var config = JsonConvert.DeserializeObject(lines); + + // windows and unix sigh... + if (file == "./ocelot.global.json" || file == ".\\ocelot.global.json") + { + fileConfiguration.GlobalConfiguration = config.GlobalConfiguration; + } + + fileConfiguration.Aggregates.AddRange(config.Aggregates); + fileConfiguration.ReRoutes.AddRange(config.ReRoutes); + } + + var json = JsonConvert.SerializeObject(fileConfiguration); + + File.WriteAllText("ocelot.json", json); + + builder.AddJsonFile("ocelot.json"); + return builder; } } diff --git a/src/Ocelot/DependencyInjection/OcelotBuilder.cs b/src/Ocelot/DependencyInjection/OcelotBuilder.cs index 96e084c1..5373cc1b 100644 --- a/src/Ocelot/DependencyInjection/OcelotBuilder.cs +++ b/src/Ocelot/DependencyInjection/OcelotBuilder.cs @@ -1,7 +1,3 @@ -using Butterfly.Client.Tracing; -using Microsoft.Extensions.Options; -using Ocelot.Middleware.Multiplexer; - namespace Ocelot.DependencyInjection { using CacheManager.Core; @@ -12,17 +8,14 @@ namespace Ocelot.DependencyInjection using Ocelot.Authorisation; using Ocelot.Cache; using Ocelot.Claims; - using Ocelot.Configuration.Authentication; using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; using Ocelot.Configuration.Parser; - using Ocelot.Configuration.Provider; using Ocelot.Configuration.Repository; using Ocelot.Configuration.Setter; using Ocelot.Configuration.Validator; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.UrlMatcher; - using Ocelot.DownstreamUrlCreator; using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer; using Ocelot.Headers; using Ocelot.Infrastructure.Claims.Parser; @@ -44,16 +37,14 @@ namespace Ocelot.DependencyInjection using System.Security.Cryptography.X509Certificates; using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; using Ocelot.Configuration; - using Ocelot.Configuration.Builder; - using FileConfigurationProvider = Ocelot.Configuration.Provider.FileConfigurationProvider; using Microsoft.Extensions.DependencyInjection.Extensions; - using System.Linq; using System.Net.Http; using Butterfly.Client.AspNetCore; using Ocelot.Infrastructure; using Ocelot.Infrastructure.Consul; + using Butterfly.Client.Tracing; + using Ocelot.Middleware.Multiplexer; public class OcelotBuilder : IOcelotBuilder { @@ -78,8 +69,8 @@ namespace Ocelot.DependencyInjection _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); - _services.TryAddSingleton(); - _services.TryAddSingleton(); + _services.TryAddSingleton(); + _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); @@ -91,9 +82,8 @@ namespace Ocelot.DependencyInjection _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); - _services.TryAddSingleton(); - _services.TryAddSingleton(); - _services.TryAddSingleton(); + _services.TryAddSingleton(); + _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); @@ -101,7 +91,6 @@ namespace Ocelot.DependencyInjection _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); - _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); _services.TryAddSingleton(); @@ -252,17 +241,6 @@ namespace Ocelot.DependencyInjection public IOcelotBuilder AddStoreOcelotConfigurationInConsul() { - var serviceDiscoveryPort = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Port", 0); - var serviceDiscoveryHost = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Host", string.Empty); - var serviceDiscoveryToken = _configurationRoot.GetValue("GlobalConfiguration:ServiceDiscoveryProvider:Token", string.Empty); - - var config = new ServiceProviderConfigurationBuilder() - .WithPort(serviceDiscoveryPort) - .WithHost(serviceDiscoveryHost) - .WithToken(serviceDiscoveryToken) - .Build(); - - _services.AddSingleton(config); _services.AddSingleton(); _services.AddSingleton(); return this; @@ -278,12 +256,12 @@ namespace Ocelot.DependencyInjection _services.AddSingleton>(cacheManagerOutputCache); _services.AddSingleton>(ocelotOutputCacheManager); - var ocelotConfigCacheManagerOutputCache = CacheFactory.Build("OcelotConfigurationCache", settings); - var ocelotConfigCacheManager = new OcelotCacheManagerCache(ocelotConfigCacheManagerOutputCache); - _services.RemoveAll(typeof(ICacheManager)); - _services.RemoveAll(typeof(IOcelotCache)); - _services.AddSingleton>(ocelotConfigCacheManagerOutputCache); - _services.AddSingleton>(ocelotConfigCacheManager); + var ocelotConfigCacheManagerOutputCache = CacheFactory.Build("OcelotConfigurationCache", settings); + var ocelotConfigCacheManager = new OcelotCacheManagerCache(ocelotConfigCacheManagerOutputCache); + _services.RemoveAll(typeof(ICacheManager)); + _services.RemoveAll(typeof(IOcelotCache)); + _services.AddSingleton>(ocelotConfigCacheManagerOutputCache); + _services.AddSingleton>(ocelotConfigCacheManager); var fileConfigCacheManagerOutputCache = CacheFactory.Build("FileConfigurationCache", settings); var fileConfigCacheManager = new OcelotCacheManagerCache(fileConfigCacheManagerOutputCache); @@ -304,7 +282,6 @@ namespace Ocelot.DependencyInjection private void AddIdentityServer(IIdentityServerConfiguration identityServerConfiguration, IAdministrationPath adminPath) { _services.TryAddSingleton(identityServerConfiguration); - _services.TryAddSingleton(); var identityServerBuilder = _services .AddIdentityServer(o => { o.IssuerUri = "Ocelot"; diff --git a/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs b/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs index 35b6d92d..df70b0b3 100644 --- a/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs @@ -18,7 +18,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder _placeholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder; } - public Response FindDownstreamRoute(string path, string httpMethod, IOcelotConfiguration configuration, string upstreamHost) + public Response FindDownstreamRoute(string path, string httpMethod, IInternalConfiguration configuration, string upstreamHost) { var downstreamRoutes = new List(); diff --git a/src/Ocelot/DownstreamRouteFinder/Finder/IDownstreamRouteFinder.cs b/src/Ocelot/DownstreamRouteFinder/Finder/IDownstreamRouteFinder.cs index 81901231..1d8fae15 100644 --- a/src/Ocelot/DownstreamRouteFinder/Finder/IDownstreamRouteFinder.cs +++ b/src/Ocelot/DownstreamRouteFinder/Finder/IDownstreamRouteFinder.cs @@ -6,6 +6,6 @@ namespace Ocelot.DownstreamRouteFinder.Finder { public interface IDownstreamRouteFinder { - Response FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IOcelotConfiguration configuration, string upstreamHost); + Response FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod, IInternalConfiguration configuration, string upstreamHost); } } diff --git a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs index 70e4a4e2..970636d3 100644 --- a/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs +++ b/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using System.Linq; -using Ocelot.Configuration; -using Ocelot.Configuration.Provider; +using Ocelot.Configuration.Repository; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.Infrastructure.Extensions; using Ocelot.Logging; @@ -14,17 +13,17 @@ namespace Ocelot.DownstreamRouteFinder.Middleware { private readonly OcelotRequestDelegate _next; private readonly IDownstreamRouteFinder _downstreamRouteFinder; - private readonly IOcelotConfigurationProvider _configProvider; + private readonly IInternalConfigurationRepository _repo; private readonly IMultiplexer _multiplexer; public DownstreamRouteFinderMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory, IDownstreamRouteFinder downstreamRouteFinder, - IOcelotConfigurationProvider configProvider, + IInternalConfigurationRepository repo, IMultiplexer multiplexer) :base(loggerFactory.CreateLogger()) { - _configProvider = configProvider; + _repo = repo; _multiplexer = multiplexer; _next = next; _downstreamRouteFinder = downstreamRouteFinder; @@ -36,7 +35,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware var upstreamHost = context.HttpContext.Request.Headers["Host"]; - var configuration = await _configProvider.Get(); + var configuration = _repo.Get(); if (configuration.IsError) { diff --git a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs index 236e2e8d..41b0b83d 100644 --- a/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs +++ b/src/Ocelot/Errors/Middleware/ExceptionHandlerMiddleware.cs @@ -1,10 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using Ocelot.Configuration.Provider; -using Ocelot.DownstreamRouteFinder.Middleware; +using Ocelot.Configuration.Repository; using Ocelot.Infrastructure.Extensions; using Ocelot.Infrastructure.RequestData; using Ocelot.Logging; @@ -18,16 +15,16 @@ namespace Ocelot.Errors.Middleware public class ExceptionHandlerMiddleware : OcelotMiddleware { private readonly OcelotRequestDelegate _next; - private readonly IOcelotConfigurationProvider _provider; + private readonly IInternalConfigurationRepository _configRepo; private readonly IRequestScopedDataRepository _repo; public ExceptionHandlerMiddleware(OcelotRequestDelegate next, - IOcelotLoggerFactory loggerFactory, - IOcelotConfigurationProvider provider, + IOcelotLoggerFactory loggerFactory, + IInternalConfigurationRepository configRepo, IRequestScopedDataRepository repo) : base(loggerFactory.CreateLogger()) { - _provider = provider; + _configRepo = configRepo; _repo = repo; _next = next; } @@ -36,7 +33,7 @@ namespace Ocelot.Errors.Middleware { try { - await TrySetGlobalRequestId(context); + TrySetGlobalRequestId(context); Logger.LogDebug("ocelot pipeline started"); @@ -56,12 +53,12 @@ namespace Ocelot.Errors.Middleware Logger.LogDebug("ocelot pipeline finished"); } - private async Task TrySetGlobalRequestId(DownstreamContext context) + private void TrySetGlobalRequestId(DownstreamContext context) { //try and get the global request id and set it for logs... //should this basically be immutable per request...i guess it should! //first thing is get config - var configuration = await _provider.Get(); + var configuration = _configRepo.Get(); if(configuration.IsError) { diff --git a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs index 9d345dc2..25d818c5 100644 --- a/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs +++ b/src/Ocelot/Middleware/OcelotMiddlewareExtensions.cs @@ -4,14 +4,12 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using System.Diagnostics; using Microsoft.AspNetCore.Builder; using Ocelot.Configuration; using Ocelot.Configuration.Creator; using Ocelot.Configuration.File; - using Ocelot.Configuration.Provider; using Ocelot.Configuration.Repository; using Ocelot.Configuration.Setter; using Ocelot.Responses; @@ -85,63 +83,108 @@ node.Start(nodeId.Id); } - private static async Task CreateConfiguration(IApplicationBuilder builder) + private static async Task CreateConfiguration(IApplicationBuilder builder) { - var deps = GetDependencies(builder); + // make configuration from file system? + // earlier user needed to add ocelot files in startup configuration stuff, asp.net will map it to this + var fileConfig = (IOptions)builder.ApplicationServices.GetService(typeof(IOptions)); + + // now create the config + var internalConfigCreator = (IInternalConfigurationCreator)builder.ApplicationServices.GetService(typeof(IInternalConfigurationCreator)); + var internalConfig = await internalConfigCreator.Create(fileConfig.Value); - var ocelotConfiguration = await deps.provider.Get(); + // now save it in memory + var internalConfigRepo = (IInternalConfigurationRepository)builder.ApplicationServices.GetService(typeof(IInternalConfigurationRepository)); + internalConfigRepo.AddOrReplace(internalConfig.Data); - if (ConfigurationNotSetUp(ocelotConfiguration)) + var fileConfigSetter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter)); + + var fileConfigRepo = (IFileConfigurationRepository)builder.ApplicationServices.GetService(typeof(IFileConfigurationRepository)); + + if (UsingConsul(fileConfigRepo)) { - var response = await SetConfig(builder, deps.fileConfiguration, deps.setter, deps.provider, deps.repo); - - if (UnableToSetConfig(response)) + await SetFileConfigInConsul(builder, fileConfigRepo, fileConfig, internalConfigCreator, internalConfigRepo); + } + else + { + await SetFileConfig(fileConfigSetter, fileConfig); + } + + return GetOcelotConfigAndReturn(internalConfigRepo); + } + + private static async Task SetFileConfigInConsul(IApplicationBuilder builder, + IFileConfigurationRepository fileConfigRepo, IOptions fileConfig, + IInternalConfigurationCreator internalConfigCreator, IInternalConfigurationRepository internalConfigRepo) + { + // get the config from consul. + var fileConfigFromConsul = await fileConfigRepo.Get(); + + if (IsError(fileConfigFromConsul)) + { + ThrowToStopOcelotStarting(fileConfigFromConsul); + } + else if (ConfigNotStoredInConsul(fileConfigFromConsul)) + { + //there was no config in consul set the file in config in consul + await fileConfigRepo.Set(fileConfig.Value); + } + else + { + // create the internal config from consul data + var internalConfig = await internalConfigCreator.Create(fileConfigFromConsul.Data); + + if (IsError(internalConfig)) { - ThrowToStopOcelotStarting(response); + ThrowToStopOcelotStarting(internalConfig); + } + else + { + // add the internal config to the internal repo + var response = internalConfigRepo.AddOrReplace(internalConfig.Data); + + if (IsError(response)) + { + ThrowToStopOcelotStarting(response); + } + } + + if (IsError(internalConfig)) + { + ThrowToStopOcelotStarting(internalConfig); } } - return await GetOcelotConfigAndReturn(deps.provider); + //todo - this starts the poller if it has been registered...please this is so bad. + var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller)); } - private static async Task SetConfig(IApplicationBuilder builder, IOptions fileConfiguration, IFileConfigurationSetter setter, IOcelotConfigurationProvider provider, IFileConfigurationRepository repo) + private static async Task SetFileConfig(IFileConfigurationSetter fileConfigSetter, IOptions fileConfig) { - if (UsingConsul(repo)) + Response response; + response = await fileConfigSetter.Set(fileConfig.Value); + + if (IsError(response)) { - return await SetUpConfigFromConsul(builder, repo, setter, fileConfiguration); + ThrowToStopOcelotStarting(response); } - - return await setter.Set(fileConfiguration.Value); } - private static bool UnableToSetConfig(Response response) + private static bool ConfigNotStoredInConsul(Responses.Response fileConfigFromConsul) + { + return fileConfigFromConsul.Data == null; + } + + private static bool IsError(Response response) { return response == null || response.IsError; } - private static bool ConfigurationNotSetUp(Ocelot.Responses.Response ocelotConfiguration) + private static IInternalConfiguration GetOcelotConfigAndReturn(IInternalConfigurationRepository provider) { - return ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError; - } + var ocelotConfiguration = provider.Get(); - private static (IOptions fileConfiguration, IFileConfigurationSetter setter, IOcelotConfigurationProvider provider, IFileConfigurationRepository repo) GetDependencies(IApplicationBuilder builder) - { - var fileConfiguration = (IOptions)builder.ApplicationServices.GetService(typeof(IOptions)); - - var setter = (IFileConfigurationSetter)builder.ApplicationServices.GetService(typeof(IFileConfigurationSetter)); - - var provider = (IOcelotConfigurationProvider)builder.ApplicationServices.GetService(typeof(IOcelotConfigurationProvider)); - - var repo = (IFileConfigurationRepository)builder.ApplicationServices.GetService(typeof(IFileConfigurationRepository)); - - return (fileConfiguration, setter, provider, repo); - } - - private static async Task GetOcelotConfigAndReturn(IOcelotConfigurationProvider provider) - { - var ocelotConfiguration = await provider.Get(); - - if(ocelotConfiguration == null || ocelotConfiguration.Data == null || ocelotConfiguration.IsError) + if(ocelotConfiguration?.Data == null || ocelotConfiguration.IsError) { ThrowToStopOcelotStarting(ocelotConfiguration); } @@ -159,49 +202,7 @@ return fileConfigRepo.GetType() == typeof(ConsulFileConfigurationRepository); } - private static async Task SetUpConfigFromConsul(IApplicationBuilder builder, IFileConfigurationRepository consulFileConfigRepo, IFileConfigurationSetter setter, IOptions fileConfig) - { - Response config = null; - - var ocelotConfigurationRepository = - (IOcelotConfigurationRepository) builder.ApplicationServices.GetService( - typeof(IOcelotConfigurationRepository)); - - var ocelotConfigurationCreator = - (IOcelotConfigurationCreator) builder.ApplicationServices.GetService( - typeof(IOcelotConfigurationCreator)); - - var fileConfigFromConsul = await consulFileConfigRepo.Get(); - - if (fileConfigFromConsul.Data == null) - { - config = await setter.Set(fileConfig.Value); - var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller)); - } - else - { - var ocelotConfig = await ocelotConfigurationCreator.Create(fileConfigFromConsul.Data); - - if(ocelotConfig.IsError) - { - return new ErrorResponse(ocelotConfig.Errors); - } - - config = await ocelotConfigurationRepository.AddOrReplace(ocelotConfig.Data); - - if (config.IsError) - { - return new ErrorResponse(config.Errors); - } - - //todo - this starts the poller if it has been registered...please this is so bad. - var hack = builder.ApplicationServices.GetService(typeof(ConsulFileConfigurationPoller)); - } - - return new OkResponse(); - } - - private static void CreateAdministrationArea(IApplicationBuilder builder, IOcelotConfiguration configuration) + private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration) { if(!string.IsNullOrEmpty(configuration.AdministrationPath)) { diff --git a/src/Ocelot/Raft/FilePeersProvider.cs b/src/Ocelot/Raft/FilePeersProvider.cs index d31dc2ca..52b877df 100644 --- a/src/Ocelot/Raft/FilePeersProvider.cs +++ b/src/Ocelot/Raft/FilePeersProvider.cs @@ -1,10 +1,8 @@ -using System; using System.Collections.Generic; using System.Net.Http; -using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Options; using Ocelot.Configuration; -using Ocelot.Configuration.Provider; +using Ocelot.Configuration.Repository; using Ocelot.Middleware; using Rafty.Concensus; using Rafty.Infrastructure; @@ -15,21 +13,20 @@ namespace Ocelot.Raft public class FilePeersProvider : IPeersProvider { private readonly IOptions _options; - private List _peers; + private readonly List _peers; private IBaseUrlFinder _finder; - private IOcelotConfigurationProvider _provider; + private IInternalConfigurationRepository _repo; private IIdentityServerConfiguration _identityServerConfig; - public FilePeersProvider(IOptions options, IBaseUrlFinder finder, IOcelotConfigurationProvider provider, IIdentityServerConfiguration identityServerConfig) + public FilePeersProvider(IOptions options, IBaseUrlFinder finder, IInternalConfigurationRepository repo, IIdentityServerConfiguration identityServerConfig) { _identityServerConfig = identityServerConfig; - _provider = provider; + _repo = repo; _finder = finder; _options = options; _peers = new List(); - //todo - sort out async nonsense.. - var config = _provider.Get().GetAwaiter().GetResult(); + var config = _repo.Get(); foreach (var item in _options.Value.Peers) { var httpClient = new HttpClient(); diff --git a/src/Ocelot/Raft/HttpPeer.cs b/src/Ocelot/Raft/HttpPeer.cs index cd5ceef5..fcec77ea 100644 --- a/src/Ocelot/Raft/HttpPeer.cs +++ b/src/Ocelot/Raft/HttpPeer.cs @@ -1,12 +1,8 @@ using System; using System.Collections.Generic; using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting; using Newtonsoft.Json; -using Ocelot.Authentication; using Ocelot.Configuration; -using Ocelot.Configuration.Provider; using Ocelot.Middleware; using Rafty.Concensus; using Rafty.FiniteStateMachine; @@ -16,15 +12,15 @@ namespace Ocelot.Raft [ExcludeFromCoverage] public class HttpPeer : IPeer { - private string _hostAndPort; - private HttpClient _httpClient; - private JsonSerializerSettings _jsonSerializerSettings; - private string _baseSchemeUrlAndPort; + private readonly string _hostAndPort; + private readonly HttpClient _httpClient; + private readonly JsonSerializerSettings _jsonSerializerSettings; + private readonly string _baseSchemeUrlAndPort; private BearerToken _token; - private IOcelotConfiguration _config; - private IIdentityServerConfiguration _identityServerConfiguration; + private readonly IInternalConfiguration _config; + private readonly IIdentityServerConfiguration _identityServerConfiguration; - public HttpPeer(string hostAndPort, HttpClient httpClient, IBaseUrlFinder finder, IOcelotConfiguration config, IIdentityServerConfiguration identityServerConfiguration) + public HttpPeer(string hostAndPort, HttpClient httpClient, IBaseUrlFinder finder, IInternalConfiguration config, IIdentityServerConfiguration identityServerConfiguration) { _identityServerConfiguration = identityServerConfiguration; _config = config; diff --git a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs index 797f340c..5a5cce82 100644 --- a/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs +++ b/test/Ocelot.AcceptanceTests/ConfigurationInConsulTests.cs @@ -303,7 +303,7 @@ namespace Ocelot.AcceptanceTests { app.Run(async context => { - if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration") + if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/InternalConfiguration") { var json = JsonConvert.SerializeObject(_config); @@ -315,7 +315,7 @@ namespace Ocelot.AcceptanceTests await context.Response.WriteJsonAsync(new FakeConsulGetResponse[] { kvp }); } - else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/OcelotConfiguration") + else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/InternalConfiguration") { try { @@ -352,7 +352,7 @@ namespace Ocelot.AcceptanceTests public int CreateIndex => 100; public int ModifyIndex => 200; public int LockIndex => 200; - public string Key => "OcelotConfiguration"; + public string Key => "InternalConfiguration"; public int Flags => 0; public string Value { get; private set; } public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e"; diff --git a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs index 341986fe..422348d0 100644 --- a/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs +++ b/test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs @@ -26,7 +26,7 @@ namespace Ocelot.AcceptanceTests { _counter = 0; _steps = new Steps(); - _configurationPath = "configuration.json"; + _configurationPath = "ocelot.json"; } [Fact] diff --git a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj index 4f67b970..18ff45f1 100644 --- a/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj +++ b/test/Ocelot.AcceptanceTests/Ocelot.AcceptanceTests.csproj @@ -15,7 +15,7 @@ - + PreserveNewest diff --git a/test/Ocelot.AcceptanceTests/Steps.cs b/test/Ocelot.AcceptanceTests/Steps.cs index ba0da5d1..f5c186ca 100644 --- a/test/Ocelot.AcceptanceTests/Steps.cs +++ b/test/Ocelot.AcceptanceTests/Steps.cs @@ -66,7 +66,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureLogging((hostingContext, logging) => @@ -124,7 +124,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -152,7 +152,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -190,7 +190,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -221,7 +221,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -254,7 +254,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -287,7 +287,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -319,7 +319,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -358,7 +358,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -400,7 +400,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -437,7 +437,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -465,7 +465,7 @@ namespace Ocelot.AcceptanceTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(s => @@ -525,7 +525,7 @@ namespace Ocelot.AcceptanceTests var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); var configuration = builder.Build(); diff --git a/test/Ocelot.AcceptanceTests/TestConfiguration.cs b/test/Ocelot.AcceptanceTests/TestConfiguration.cs index 5f29d1bd..6f5818ca 100644 --- a/test/Ocelot.AcceptanceTests/TestConfiguration.cs +++ b/test/Ocelot.AcceptanceTests/TestConfiguration.cs @@ -5,6 +5,6 @@ namespace Ocelot.AcceptanceTests { public static class TestConfiguration { - public static string ConfigurationPath => Path.Combine(AppContext.BaseDirectory, "configuration.json"); + public static string ConfigurationPath => Path.Combine(AppContext.BaseDirectory, "ocelot.json"); } } diff --git a/test/Ocelot.AcceptanceTests/configuration.json b/test/Ocelot.AcceptanceTests/configuration.json deleted file mode 100755 index 027025b0..00000000 --- a/test/Ocelot.AcceptanceTests/configuration.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "ReRoutes": [ - { - "DownstreamPathTemplate": "41879/", - "UpstreamPathTemplate": "/", - "UpstreamHttpMethod": "Get", - "AuthenticationOptions": { - "Provider": null, - "ProviderRootUrl": null, - "ApiName": null, - "RequireHttps": false, - "AllowedScopes": [], - "ApiSecret": null - }, - "AddHeadersToRequest": {}, - "AddClaimsToRequest": {}, - "RouteClaimsRequirement": {}, - "AddQueriesToRequest": {}, - "RequestIdKey": null, - "FileCacheOptions": { - "TtlSeconds": 0 - }, - "ReRouteIsCaseSensitive": false, - "ServiceName": null, - "DownstreamScheme": "http", - "DownstreamHost": "localhost", - "DownstreamPort": 41879, - "QoSOptions": { - "ExceptionsAllowedBeforeBreaking": 0, - "DurationOfBreak": 0, - "TimeoutValue": 0 - }, - "LoadBalancer": null, - "RateLimitOptions": { - "ClientWhitelist": [], - "EnableRateLimiting": false, - "Period": null, - "PeriodTimespan": 0, - "Limit": 0 - } - } - ], - "GlobalConfiguration": { - "RequestIdKey": null, - "ServiceDiscoveryProvider": { - "Provider": null, - "Host": null, - "Port": 0 - }, - "AdministrationPath": null, - "RateLimitOptions": { - "ClientIdHeader": "ClientId", - "QuotaExceededMessage": null, - "RateLimitCounterPrefix": "ocelot", - "DisableRateLimitHeaders": false, - "HttpStatusCode": 429 - } - } -} \ No newline at end of file diff --git a/test/Ocelot.IntegrationTests/AdministrationTests.cs b/test/Ocelot.IntegrationTests/AdministrationTests.cs index 763d642c..84b0c0bb 100644 --- a/test/Ocelot.IntegrationTests/AdministrationTests.cs +++ b/test/Ocelot.IntegrationTests/AdministrationTests.cs @@ -461,7 +461,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(x => @@ -579,7 +579,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(x => { @@ -612,7 +612,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(x => @@ -652,7 +652,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(x => { @@ -675,7 +675,7 @@ namespace Ocelot.IntegrationTests private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) { - var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; + var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json"; var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); @@ -688,7 +688,7 @@ namespace Ocelot.IntegrationTests var text = File.ReadAllText(configurationPath); - configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; + configurationPath = $"{AppContext.BaseDirectory}/ocelot.json"; if (File.Exists(configurationPath)) { diff --git a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj index 644d217b..97c8782f 100644 --- a/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj +++ b/test/Ocelot.IntegrationTests/Ocelot.IntegrationTests.csproj @@ -14,7 +14,7 @@ ..\..\codeanalysis.ruleset - + PreserveNewest diff --git a/test/Ocelot.IntegrationTests/RaftTests.cs b/test/Ocelot.IntegrationTests/RaftTests.cs index 3dc01bb9..baad5091 100644 --- a/test/Ocelot.IntegrationTests/RaftTests.cs +++ b/test/Ocelot.IntegrationTests/RaftTests.cs @@ -301,7 +301,7 @@ namespace Ocelot.IntegrationTests private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) { - var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; + var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json"; var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); @@ -314,7 +314,7 @@ namespace Ocelot.IntegrationTests var text = File.ReadAllText(configurationPath); - configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; + configurationPath = $"{AppContext.BaseDirectory}/ocelot.json"; if (File.Exists(configurationPath)) { @@ -340,7 +340,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddJsonFile("peers.json", optional: true, reloadOnChange: true); #pragma warning disable CS0618 config.AddOcelotBaseUrl(url); diff --git a/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs b/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs index e61fa63b..ed125aa4 100644 --- a/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs +++ b/test/Ocelot.IntegrationTests/ThreadSafeHeadersTests.cs @@ -108,7 +108,7 @@ namespace Ocelot.IntegrationTests var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); - config.AddJsonFile("configuration.json"); + config.AddJsonFile("ocelot.json"); config.AddEnvironmentVariables(); }) .ConfigureServices(x => @@ -138,7 +138,7 @@ namespace Ocelot.IntegrationTests private void GivenThereIsAConfiguration(FileConfiguration fileConfiguration) { - var configurationPath = $"{Directory.GetCurrentDirectory()}/configuration.json"; + var configurationPath = $"{Directory.GetCurrentDirectory()}/ocelot.json"; var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); @@ -151,7 +151,7 @@ namespace Ocelot.IntegrationTests var text = File.ReadAllText(configurationPath); - configurationPath = $"{AppContext.BaseDirectory}/configuration.json"; + configurationPath = $"{AppContext.BaseDirectory}/ocelot.json"; if (File.Exists(configurationPath)) { diff --git a/test/Ocelot.IntegrationTests/configuration.json b/test/Ocelot.IntegrationTests/ocelot.json old mode 100755 new mode 100644 similarity index 100% rename from test/Ocelot.IntegrationTests/configuration.json rename to test/Ocelot.IntegrationTests/ocelot.json diff --git a/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj b/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj index d2e3e7bc..a43e6b23 100644 --- a/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj +++ b/test/Ocelot.ManualTest/Ocelot.ManualTest.csproj @@ -16,7 +16,7 @@ - + PreserveNewest diff --git a/test/Ocelot.ManualTest/Program.cs b/test/Ocelot.ManualTest/Program.cs index 3bab21b7..966b1097 100644 --- a/test/Ocelot.ManualTest/Program.cs +++ b/test/Ocelot.ManualTest/Program.cs @@ -21,7 +21,7 @@ namespace Ocelot.ManualTest .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) - .AddJsonFile("configuration.json") + .AddJsonFile("ocelot.json") .AddEnvironmentVariables(); }) .ConfigureServices(s => { diff --git a/test/Ocelot.ManualTest/configuration.json b/test/Ocelot.ManualTest/ocelot.json similarity index 100% rename from test/Ocelot.ManualTest/configuration.json rename to test/Ocelot.ManualTest/ocelot.json diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs index 479c3e28..40fe4f02 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationCreatorTests.cs @@ -1,22 +1,18 @@ -using System.Collections.Generic; -using Castle.Components.DictionaryAdapter; -using Microsoft.Extensions.Options; -using Moq; -using Ocelot.Cache; -using Ocelot.Configuration; -using Ocelot.Configuration.Builder; -using Ocelot.Configuration.Creator; -using Ocelot.Configuration.File; -using Ocelot.Configuration.Validator; -using Ocelot.Logging; -using Ocelot.Responses; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.Configuration +namespace Ocelot.UnitTests.Configuration { - using System; + using System.Collections.Generic; + using Moq; + using Ocelot.Cache; + using Ocelot.Configuration; + using Ocelot.Configuration.Builder; + using Ocelot.Configuration.Creator; + using Ocelot.Configuration.File; + using Ocelot.Configuration.Validator; + using Ocelot.Logging; + using Ocelot.Responses; + using Shouldly; + using TestStack.BDDfy; + using Xunit; using Ocelot.DependencyInjection; using Ocelot.Errors; using Ocelot.UnitTests.TestData; @@ -24,23 +20,22 @@ namespace Ocelot.UnitTests.Configuration public class FileConfigurationCreatorTests { - private readonly Mock> _fileConfig; private readonly Mock _validator; - private Response _config; + private Response _config; private FileConfiguration _fileConfiguration; private readonly Mock _logger; - private readonly FileOcelotConfigurationCreator _ocelotConfigurationCreator; - private Mock _claimsToThingCreator; - private Mock _authOptionsCreator; - private Mock _upstreamTemplatePatternCreator; - private Mock _requestIdKeyCreator; - private Mock _serviceProviderConfigCreator; - private Mock _qosOptionsCreator; - private Mock _fileReRouteOptionsCreator; - private Mock _rateLimitOptions; - private Mock _regionCreator; - private Mock _httpHandlerOptionsCreator; - private Mock _adminPath; + private readonly FileInternalConfigurationCreator _internalConfigurationCreator; + private readonly Mock _claimsToThingCreator; + private readonly Mock _authOptionsCreator; + private readonly Mock _upstreamTemplatePatternCreator; + private readonly Mock _requestIdKeyCreator; + private readonly Mock _serviceProviderConfigCreator; + private readonly Mock _qosOptionsCreator; + private readonly Mock _fileReRouteOptionsCreator; + private readonly Mock _rateLimitOptions; + private readonly Mock _regionCreator; + private readonly Mock _httpHandlerOptionsCreator; + private readonly Mock _adminPath; private readonly Mock _headerFindAndReplaceCreator; private readonly Mock _downstreamAddressesCreator; @@ -48,7 +43,6 @@ namespace Ocelot.UnitTests.Configuration { _logger = new Mock(); _validator = new Mock(); - _fileConfig = new Mock>(); _claimsToThingCreator = new Mock(); _authOptionsCreator = new Mock(); _upstreamTemplatePatternCreator = new Mock(); @@ -63,8 +57,7 @@ namespace Ocelot.UnitTests.Configuration _headerFindAndReplaceCreator = new Mock(); _downstreamAddressesCreator = new Mock(); - _ocelotConfigurationCreator = new FileOcelotConfigurationCreator( - _fileConfig.Object, + _internalConfigurationCreator = new FileInternalConfigurationCreator( _validator.Object, _logger.Object, _claimsToThingCreator.Object, @@ -262,7 +255,7 @@ namespace Ocelot.UnitTests.Configuration .And(x => x.GivenTheConfigIsValid()) .And(x => x.GivenTheFollowingRegionIsReturned("region")) .When(x => x.WhenICreateTheConfig()) - .Then(x => x.ThenTheRegionCreatorIsCalledCorrectly("region")) + .Then(x => x.ThenTheRegionCreatorIsCalledCorrectly()) .And(x => x.ThenTheHeaderFindAndReplaceCreatorIsCalledCorrectly()) .BDDfy(); } @@ -800,14 +793,11 @@ namespace Ocelot.UnitTests.Configuration private void GivenTheConfigIs(FileConfiguration fileConfiguration) { _fileConfiguration = fileConfiguration; - _fileConfig - .Setup(x => x.Value) - .Returns(_fileConfiguration); } private void WhenICreateTheConfig() { - _config = _ocelotConfigurationCreator.Create(_fileConfiguration).Result; + _config = _internalConfigurationCreator.Create(_fileConfiguration).Result; } private void ThenTheReRoutesAre(List expectedReRoutes) @@ -928,7 +918,7 @@ namespace Ocelot.UnitTests.Configuration .Returns(region); } - private void ThenTheRegionCreatorIsCalledCorrectly(string expected) + private void ThenTheRegionCreatorIsCalledCorrectly() { _regionCreator .Verify(x => x.Create(_fileConfiguration.ReRoutes[0]), Times.Once); diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs deleted file mode 100644 index 506da50c..00000000 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationProviderTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using Moq; -using Ocelot.Configuration; -using Ocelot.Configuration.File; -using Ocelot.Responses; -using Shouldly; -using TestStack.BDDfy; -using Xunit; -using Newtonsoft.Json; -using System.IO; -using Ocelot.Configuration.Provider; -using Ocelot.Configuration.Repository; - -namespace Ocelot.UnitTests.Configuration -{ - public class FileConfigurationProviderTests - { - private readonly IFileConfigurationProvider _provider; - private Mock _repo; - private FileConfiguration _result; - private FileConfiguration _fileConfiguration; - - public FileConfigurationProviderTests() - { - _repo = new Mock(); - _provider = new FileConfigurationProvider(_repo.Object); - } - - [Fact] - public void should_return_file_configuration() - { - var config = new FileConfiguration(); - - this.Given(x => x.GivenTheConfigurationIs(config)) - .When(x => x.WhenIGetTheReRoutes()) - .Then(x => x.ThenTheRepoIsCalledCorrectly()) - .BDDfy(); - } - - private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) - { - _fileConfiguration = fileConfiguration; - _repo - .Setup(x => x.Get()) - .ReturnsAsync(new OkResponse(fileConfiguration)); - } - - private void WhenIGetTheReRoutes() - { - _result = _provider.Get().Result.Data; - } - - private void ThenTheRepoIsCalledCorrectly() - { - _repo - .Verify(x => x.Get(), Times.Once); - } - } -} diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs index 15dd3729..5b0e93db 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationRepositoryTests.cs @@ -18,12 +18,16 @@ namespace Ocelot.UnitTests.Configuration private IFileConfigurationRepository _repo; private FileConfiguration _result; private FileConfiguration _fileConfiguration; - private string _environmentName = "DEV"; + + // This is a bit dirty and it is dev.dev so that the ConfigurationBuilderExtensionsTests + // cant pick it up if they run in parralel..sigh these are not really unit + // tests but whatever... + private string _environmentName = "DEV.DEV"; public FileConfigurationRepositoryTests() { _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName); - _repo = new FileConfigurationRepository(_hostingEnvironment.Object); + _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object); } [Fact] @@ -75,7 +79,7 @@ namespace Ocelot.UnitTests.Configuration { _environmentName = null; _hostingEnvironment.Setup(he => he.EnvironmentName).Returns(_environmentName); - _repo = new FileConfigurationRepository(_hostingEnvironment.Object); + _repo = new DiskFileConfigurationRepository(_hostingEnvironment.Object); } private void GivenIHaveAConfiguration(FileConfiguration fileConfiguration) @@ -113,7 +117,7 @@ namespace Ocelot.UnitTests.Configuration private void GivenTheConfigurationIs(FileConfiguration fileConfiguration) { - var configurationPath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json"; + var configurationPath = $"{AppContext.BaseDirectory}/ocelot{(string.IsNullOrEmpty(_environmentName) ? string.Empty : ".")}{_environmentName}.json"; var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration); diff --git a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs index e16148f2..ff33872c 100644 --- a/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs +++ b/test/Ocelot.UnitTests/Configuration/FileConfigurationSetterTests.cs @@ -18,19 +18,19 @@ namespace Ocelot.UnitTests.Configuration public class FileConfigurationSetterTests { private FileConfiguration _fileConfiguration; - private FileConfigurationSetter _configSetter; - private Mock _configRepo; - private Mock _configCreator; - private Response _configuration; + private FileAndInternalConfigurationSetter _configSetter; + private Mock _configRepo; + private Mock _configCreator; + private Response _configuration; private object _result; private Mock _repo; public FileConfigurationSetterTests() { _repo = new Mock(); - _configRepo = new Mock(); - _configCreator = new Mock(); - _configSetter = new FileConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object); + _configRepo = new Mock(); + _configCreator = new Mock(); + _configSetter = new FileAndInternalConfigurationSetter(_configRepo.Object, _configCreator.Object, _repo.Object); } [Fact] @@ -38,11 +38,11 @@ namespace Ocelot.UnitTests.Configuration { var fileConfig = new FileConfiguration(); var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); - var config = new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig, "asdf"); + var config = new InternalConfiguration(new List(), string.Empty, serviceProviderConfig, "asdf"); this.Given(x => GivenTheFollowingConfiguration(fileConfig)) .And(x => GivenTheRepoReturns(new OkResponse())) - .And(x => GivenTheCreatorReturns(new OkResponse(config))) + .And(x => GivenTheCreatorReturns(new OkResponse(config))) .When(x => WhenISetTheConfiguration()) .Then(x => ThenTheConfigurationRepositoryIsCalledCorrectly()) .BDDfy(); @@ -67,7 +67,7 @@ namespace Ocelot.UnitTests.Configuration this.Given(x => GivenTheFollowingConfiguration(fileConfig)) .And(x => GivenTheRepoReturns(new OkResponse())) - .And(x => GivenTheCreatorReturns(new ErrorResponse(It.IsAny()))) + .And(x => GivenTheCreatorReturns(new ErrorResponse(It.IsAny()))) .When(x => WhenISetTheConfiguration()) .And(x => ThenAnErrorResponseIsReturned()) .BDDfy(); @@ -85,7 +85,7 @@ namespace Ocelot.UnitTests.Configuration _result.ShouldBeOfType(); } - private void GivenTheCreatorReturns(Response configuration) + private void GivenTheCreatorReturns(Response configuration) { _configuration = configuration; _configCreator diff --git a/test/Ocelot.UnitTests/Configuration/HashMatcherTests.cs b/test/Ocelot.UnitTests/Configuration/HashMatcherTests.cs deleted file mode 100644 index 55c5edc9..00000000 --- a/test/Ocelot.UnitTests/Configuration/HashMatcherTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Ocelot.Configuration.Authentication; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.Configuration -{ - public class HashMatcherTests - { - private string _password; - private string _hash; - private string _salt; - private bool _result; - private HashMatcher _hashMatcher; - - public HashMatcherTests() - { - _hashMatcher = new HashMatcher(); - } - - [Fact] - public void should_match_hash() - { - var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4="; - var salt = "zzWITpnDximUNKYLiUam/w=="; - var password = "secret"; - - this.Given(x => GivenThePassword(password)) - .And(x => GivenTheHash(hash)) - .And(x => GivenTheSalt(salt)) - .When(x => WhenIMatch()) - .Then(x => ThenTheResultIs(true)) - .BDDfy(); - } - - [Fact] - public void should_not_match_hash() - { - var hash = "kE/mxd1hO9h9Sl2VhGhwJUd9xZEv4NP6qXoN39nIqM4="; - var salt = "zzWITpnDximUNKYLiUam/w=="; - var password = "secret1"; - - this.Given(x => GivenThePassword(password)) - .And(x => GivenTheHash(hash)) - .And(x => GivenTheSalt(salt)) - .When(x => WhenIMatch()) - .Then(x => ThenTheResultIs(false)) - .BDDfy(); - } - - private void GivenThePassword(string password) - { - _password = password; - } - - private void GivenTheHash(string hash) - { - _hash = hash; - } - - private void GivenTheSalt(string salt) - { - _salt = salt; - } - - private void WhenIMatch() - { - _result = _hashMatcher.Match(_password, _salt, _hash); - } - - private void ThenTheResultIs(bool expected) - { - _result.ShouldBe(expected); - } - } -} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs index df37ca8b..a8f8644a 100644 --- a/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs +++ b/test/Ocelot.UnitTests/Configuration/HeaderFindAndReplaceCreatorTests.cs @@ -149,6 +149,7 @@ namespace Ocelot.UnitTests.Configuration .Then(x => ThenTheFollowingDownstreamIsReturned(downstream)) .BDDfy(); } + [Fact] public void should_add_trace_id_header() { diff --git a/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs b/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs index cdc3f94d..50bf1f85 100644 --- a/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs +++ b/test/Ocelot.UnitTests/Configuration/InMemoryConfigurationRepositoryTests.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Ocelot.Configuration; using Ocelot.Configuration.Builder; using Ocelot.Configuration.Repository; @@ -14,14 +12,14 @@ namespace Ocelot.UnitTests.Configuration { public class InMemoryConfigurationRepositoryTests { - private readonly InMemoryOcelotConfigurationRepository _repo; - private IOcelotConfiguration _config; + private readonly InMemoryInternalConfigurationRepository _repo; + private IInternalConfiguration _config; private Response _result; - private Response _getResult; + private Response _getResult; public InMemoryConfigurationRepositoryTests() { - _repo = new InMemoryOcelotConfigurationRepository(); + _repo = new InMemoryInternalConfigurationRepository(); } [Fact] @@ -49,7 +47,7 @@ namespace Ocelot.UnitTests.Configuration private void WhenIGetTheConfiguration() { - _getResult = _repo.Get().Result; + _getResult = _repo.Get(); } private void GivenThereIsASavedConfiguration() @@ -58,14 +56,14 @@ namespace Ocelot.UnitTests.Configuration WhenIAddOrReplaceTheConfig(); } - private void GivenTheConfigurationIs(IOcelotConfiguration config) + private void GivenTheConfigurationIs(IInternalConfiguration config) { _config = config; } private void WhenIAddOrReplaceTheConfig() { - _result = _repo.AddOrReplace(_config).Result; + _result = _repo.AddOrReplace(_config); } private void ThenNoErrorsAreReturned() @@ -73,7 +71,7 @@ namespace Ocelot.UnitTests.Configuration _result.IsError.ShouldBeFalse(); } - class FakeConfig : IOcelotConfiguration + class FakeConfig : IInternalConfiguration { private readonly string _downstreamTemplatePath; diff --git a/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs b/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs deleted file mode 100644 index 982fe091..00000000 --- a/test/Ocelot.UnitTests/Configuration/OcelotConfigurationProviderTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Generic; -using Moq; -using Ocelot.Configuration; -using Ocelot.Configuration.Builder; -using Ocelot.Configuration.Creator; -using Ocelot.Configuration.Provider; -using Ocelot.Configuration.Repository; -using Ocelot.Errors; -using Ocelot.Responses; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.Configuration -{ - public class OcelotConfigurationProviderTests - { - private readonly IOcelotConfigurationProvider _ocelotConfigurationProvider; - private readonly Mock _configurationRepository; - private Response _result; - - public OcelotConfigurationProviderTests() - { - _configurationRepository = new Mock(); - _ocelotConfigurationProvider = new OcelotConfigurationProvider(_configurationRepository.Object); - } - - [Fact] - public void should_get_config() - { - var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build(); - - this.Given(x => x.GivenTheRepoReturns(new OkResponse(new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig, "")))) - .When(x => x.WhenIGetTheConfig()) - .Then(x => x.TheFollowingIsReturned(new OkResponse(new OcelotConfiguration(new List(), string.Empty, serviceProviderConfig, "")))) - .BDDfy(); - } - - [Fact] - public void should_return_error() - { - this.Given(x => x.GivenTheRepoReturns(new ErrorResponse(new List - { - new AnyError() - }))) - .When(x => x.WhenIGetTheConfig()) - .Then(x => x.TheFollowingIsReturned( - new ErrorResponse(new List - { - new AnyError() - }))) - .BDDfy(); - } - - private void GivenTheRepoReturns(Response config) - { - _configurationRepository - .Setup(x => x.Get()) - .ReturnsAsync(config); - } - - private void WhenIGetTheConfig() - { - _result = _ocelotConfigurationProvider.Get().Result; - } - - private void TheFollowingIsReturned(Response expected) - { - _result.IsError.ShouldBe(expected.IsError); - } - - class AnyError : Error - { - public AnyError() - : base("blamo", OcelotErrorCode.UnknownError) - { - } - } - } -} diff --git a/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs b/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs index c0ae8b87..520d8274 100644 --- a/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs +++ b/test/Ocelot.UnitTests/Controllers/FileConfigurationControllerTests.cs @@ -8,32 +8,30 @@ using Ocelot.Responses; using TestStack.BDDfy; using Xunit; using Shouldly; -using Ocelot.Configuration.Provider; -using Microsoft.Extensions.DependencyInjection; using Ocelot.Raft; using Rafty.Concensus; -using Newtonsoft.Json; -using Rafty.FiniteStateMachine; using Ocelot.Configuration; namespace Ocelot.UnitTests.Controllers { + using Ocelot.Configuration.Repository; + public class FileConfigurationControllerTests { - private FileConfigurationController _controller; - private Mock _configGetter; - private Mock _configSetter; + private readonly FileConfigurationController _controller; + private readonly Mock _repo; + private readonly Mock _setter; private IActionResult _result; private FileConfiguration _fileConfiguration; - private Mock _provider; + private readonly Mock _provider; private Mock _node; public FileConfigurationControllerTests() { _provider = new Mock(); - _configGetter = new Mock(); - _configSetter = new Mock(); - _controller = new FileConfigurationController(_configGetter.Object, _configSetter.Object, _provider.Object); + _repo = new Mock(); + _setter = new Mock(); + _controller = new FileConfigurationController(_repo.Object, _setter.Object, _provider.Object); } [Fact] @@ -140,14 +138,14 @@ namespace Ocelot.UnitTests.Controllers private void GivenTheConfigSetterReturns(Response response) { - _configSetter + _setter .Setup(x => x.Set(It.IsAny())) .ReturnsAsync(response); } private void ThenTheConfigrationSetterIsCalledCorrectly() { - _configSetter + _setter .Verify(x => x.Set(_fileConfiguration), Times.Once); } @@ -168,7 +166,7 @@ namespace Ocelot.UnitTests.Controllers private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response fileConfiguration) { - _configGetter + _repo .Setup(x => x.Get()) .ReturnsAsync(fileConfiguration); } @@ -180,7 +178,7 @@ namespace Ocelot.UnitTests.Controllers private void TheTheGetFileConfigurationIsCalledCorrectly() { - _configGetter + _repo .Verify(x => x.Get(), Times.Once); } diff --git a/test/Ocelot.UnitTests/DependencyInjection/ConfigurationBuilderExtensionsTests.cs b/test/Ocelot.UnitTests/DependencyInjection/ConfigurationBuilderExtensionsTests.cs index 5d32b1ed..7c29977d 100644 --- a/test/Ocelot.UnitTests/DependencyInjection/ConfigurationBuilderExtensionsTests.cs +++ b/test/Ocelot.UnitTests/DependencyInjection/ConfigurationBuilderExtensionsTests.cs @@ -1,25 +1,213 @@ -using Microsoft.Extensions.Configuration; -using Ocelot.DependencyInjection; -using Shouldly; -using TestStack.BDDfy; -using Xunit; - -namespace Ocelot.UnitTests.DependencyInjection +namespace Ocelot.UnitTests.DependencyInjection { + using System.Collections.Generic; + using System.IO; + using Newtonsoft.Json; + using Ocelot.Configuration.File; + using Microsoft.Extensions.Configuration; + using Ocelot.DependencyInjection; + using Shouldly; + using TestStack.BDDfy; + using Xunit; + public class ConfigurationBuilderExtensionsTests { private IConfigurationRoot _configuration; private string _result; + private IConfigurationRoot _configRoot; + private FileConfiguration _globalConfig; + private FileConfiguration _reRouteA; + private FileConfiguration _reRouteB; + private FileConfiguration _aggregate; [Fact] public void should_add_base_url_to_config() { - this.Given(x => GivenTheBaseUrl("test")) - .When(x => WhenIGet("BaseUrl")) - .Then(x => ThenTheResultIs("test")) + this.Given(_ => GivenTheBaseUrl("test")) + .When(_ => WhenIGet("BaseUrl")) + .Then(_ => ThenTheResultIs("test")) .BDDfy(); } + [Fact] + public void should_merge_files() + { + this.Given(_ => GivenMultipleConfigurationFiles()) + .When(_ => WhenIAddOcelotConfiguration()) + .Then(_ => ThenTheConfigsAreMerged()) + .BDDfy(); + } + + private void GivenMultipleConfigurationFiles() + { + _globalConfig = new FileConfiguration + { + GlobalConfiguration = new FileGlobalConfiguration + { + BaseUrl = "BaseUrl", + RateLimitOptions = new FileRateLimitOptions + { + HttpStatusCode = 500, + ClientIdHeader = "ClientIdHeader", + DisableRateLimitHeaders = true, + QuotaExceededMessage = "QuotaExceededMessage", + RateLimitCounterPrefix = "RateLimitCounterPrefix" + }, + ServiceDiscoveryProvider = new FileServiceDiscoveryProvider + { + Host = "Host", + Port = 80, + Type = "Type" + }, + RequestIdKey = "RequestIdKey" + } + }; + + _reRouteA = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamScheme = "DownstreamScheme", + DownstreamPathTemplate = "DownstreamPathTemplate", + Key = "Key", + UpstreamHost = "UpstreamHost", + UpstreamHttpMethod = new List + { + "UpstreamHttpMethod" + }, + DownstreamHostAndPorts = new List + { + new FileHostAndPort + { + Host = "Host", + Port = 80 + } + } + } + } + }; + + _reRouteB = new FileConfiguration + { + ReRoutes = new List + { + new FileReRoute + { + DownstreamScheme = "DownstreamSchemeB", + DownstreamPathTemplate = "DownstreamPathTemplateB", + Key = "KeyB", + UpstreamHost = "UpstreamHostB", + UpstreamHttpMethod = new List + { + "UpstreamHttpMethodB" + }, + DownstreamHostAndPorts = new List + { + new FileHostAndPort + { + Host = "HostB", + Port = 80 + } + } + }, + new FileReRoute + { + DownstreamScheme = "DownstreamSchemeBB", + DownstreamPathTemplate = "DownstreamPathTemplateBB", + Key = "KeyBB", + UpstreamHost = "UpstreamHostBB", + UpstreamHttpMethod = new List + { + "UpstreamHttpMethodBB" + }, + DownstreamHostAndPorts = new List + { + new FileHostAndPort + { + Host = "HostBB", + Port = 80 + } + } + } + } + }; + + _aggregate = new FileConfiguration + { + Aggregates = new List + { + new FileAggregateReRoute + { + ReRouteKeys = new List + { + "KeyB", + "KeyBB" + }, + UpstreamPathTemplate = "UpstreamPathTemplate", + }, + new FileAggregateReRoute + { + ReRouteKeys = new List + { + "KeyB", + "KeyBB" + }, + UpstreamPathTemplate = "UpstreamPathTemplate", + } + } + }; + + File.WriteAllText("ocelot.global.json", JsonConvert.SerializeObject(_globalConfig)); + File.WriteAllText("ocelot.reRoutesA.json", JsonConvert.SerializeObject(_reRouteA)); + File.WriteAllText("ocelot.reRoutesB.json", JsonConvert.SerializeObject(_reRouteB)); + File.WriteAllText("ocelot.aggregates.json", JsonConvert.SerializeObject(_aggregate)); + } + + private void WhenIAddOcelotConfiguration() + { + IConfigurationBuilder builder = new ConfigurationBuilder(); + builder.AddOcelot(); + _configRoot = builder.Build(); + } + + private void ThenTheConfigsAreMerged() + { + var fc = (FileConfiguration)_configRoot.Get(typeof(FileConfiguration)); + + fc.GlobalConfiguration.BaseUrl.ShouldBe(_globalConfig.GlobalConfiguration.BaseUrl); + fc.GlobalConfiguration.RateLimitOptions.ClientIdHeader.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.ClientIdHeader); + fc.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.DisableRateLimitHeaders); + fc.GlobalConfiguration.RateLimitOptions.HttpStatusCode.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.HttpStatusCode); + fc.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.QuotaExceededMessage); + fc.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix.ShouldBe(_globalConfig.GlobalConfiguration.RateLimitOptions.RateLimitCounterPrefix); + fc.GlobalConfiguration.RequestIdKey.ShouldBe(_globalConfig.GlobalConfiguration.RequestIdKey); + fc.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Host); + fc.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Port); + fc.GlobalConfiguration.ServiceDiscoveryProvider.Type.ShouldBe(_globalConfig.GlobalConfiguration.ServiceDiscoveryProvider.Type); + + fc.ReRoutes.Count.ShouldBe(_reRouteA.ReRoutes.Count + _reRouteB.ReRoutes.Count); + + fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteA.ReRoutes[0].DownstreamPathTemplate); + fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[0].DownstreamPathTemplate); + fc.ReRoutes.ShouldContain(x => x.DownstreamPathTemplate == _reRouteB.ReRoutes[1].DownstreamPathTemplate); + + fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteA.ReRoutes[0].DownstreamScheme); + fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[0].DownstreamScheme); + fc.ReRoutes.ShouldContain(x => x.DownstreamScheme == _reRouteB.ReRoutes[1].DownstreamScheme); + + fc.ReRoutes.ShouldContain(x => x.Key == _reRouteA.ReRoutes[0].Key); + fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[0].Key); + fc.ReRoutes.ShouldContain(x => x.Key == _reRouteB.ReRoutes[1].Key); + + fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteA.ReRoutes[0].UpstreamHost); + fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[0].UpstreamHost); + fc.ReRoutes.ShouldContain(x => x.UpstreamHost == _reRouteB.ReRoutes[1].UpstreamHost); + + fc.Aggregates.Count.ShouldBe(_aggregate.Aggregates.Count); + } + private void GivenTheBaseUrl(string baseUrl) { #pragma warning disable CS0618 diff --git a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs index 0b13954a..b295a564 100644 --- a/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs +++ b/test/Ocelot.UnitTests/DependencyInjection/OcelotBuilderTests.cs @@ -325,8 +325,8 @@ namespace Ocelot.UnitTests.DependencyInjection var outputCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache)); var outputCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager)); var instance = (ICacheManager)outputCacheManager.ImplementationInstance; - var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache)); - var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager)); + var ocelotConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache)); + var ocelotConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager)); var fileConfigCache = _services.Single(x => x.ServiceType == typeof(IOcelotCache)); var fileConfigCacheManager = _services.Single(x => x.ServiceType == typeof(ICacheManager)); diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs index d3363b00..95bcaf47 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderMiddlewareTests.cs @@ -1,7 +1,4 @@ -using Ocelot.Middleware; -using Ocelot.Middleware.Multiplexer; - -namespace Ocelot.UnitTests.DownstreamRouteFinder +namespace Ocelot.UnitTests.DownstreamRouteFinder { using System.Collections.Generic; using System.Threading.Tasks; @@ -9,7 +6,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; - using Ocelot.Configuration.Provider; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.Middleware; @@ -19,23 +15,26 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder using Shouldly; using TestStack.BDDfy; using Xunit; + using Ocelot.Configuration.Repository; + using Ocelot.Middleware; + using Ocelot.Middleware.Multiplexer; public class DownstreamRouteFinderMiddlewareTests { private readonly Mock _finder; - private readonly Mock _provider; + private readonly Mock _repo; private Response _downstreamRoute; - private IOcelotConfiguration _config; + private IInternalConfiguration _config; private Mock _loggerFactory; private Mock _logger; - private DownstreamRouteFinderMiddleware _middleware; - private DownstreamContext _downstreamContext; + private readonly DownstreamRouteFinderMiddleware _middleware; + private readonly DownstreamContext _downstreamContext; private OcelotRequestDelegate _next; private readonly Mock _multiplexer; public DownstreamRouteFinderMiddlewareTests() { - _provider = new Mock(); + _repo = new Mock(); _finder = new Mock(); _downstreamContext = new DownstreamContext(new DefaultHttpContext()); _loggerFactory = new Mock(); @@ -43,13 +42,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder _loggerFactory.Setup(x => x.CreateLogger()).Returns(_logger.Object); _next = context => Task.CompletedTask; _multiplexer = new Mock(); - _middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object); + _middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _repo.Object, _multiplexer.Object); } [Fact] public void should_call_scoped_data_repository_correctly() { - var config = new OcelotConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), ""); + var config = new InternalConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), ""); var downstreamReRoute = new DownstreamReRouteBuilder() .WithDownstreamPathTemplate("any old string") @@ -74,19 +73,19 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder _middleware.Invoke(_downstreamContext).GetAwaiter().GetType(); } - private void GivenTheFollowingConfig(IOcelotConfiguration config) + private void GivenTheFollowingConfig(IInternalConfiguration config) { _config = config; - _provider + _repo .Setup(x => x.Get()) - .ReturnsAsync(new OkResponse(_config)); + .Returns(new OkResponse(_config)); } private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute) { _downstreamRoute = new OkResponse(downstreamRoute); _finder - .Setup(x => x.FindDownstreamRoute(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(x => x.FindDownstreamRoute(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(_downstreamRoute); } diff --git a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs index cb5c2a67..7406b1c5 100644 --- a/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs +++ b/test/Ocelot.UnitTests/DownstreamRouteFinder/DownstreamRouteFinderTests.cs @@ -2,8 +2,6 @@ using Moq; using Ocelot.Configuration; using Ocelot.Configuration.Builder; -using Ocelot.Configuration.Creator; -using Ocelot.Configuration.Provider; using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder.Finder; using Ocelot.DownstreamRouteFinder.UrlMatcher; @@ -23,7 +21,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder private string _upstreamUrlPath; private Response _result; private List _reRoutesConfig; - private OcelotConfiguration _config; + private InternalConfiguration _config; private Response _match; private string _upstreamHttpMethod; private string _upstreamHost; @@ -711,7 +709,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder private void GivenTheConfigurationIs(List reRoutesConfig, string adminPath, ServiceProviderConfiguration serviceProviderConfig) { _reRoutesConfig = reRoutesConfig; - _config = new OcelotConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, ""); + _config = new InternalConfiguration(_reRoutesConfig, adminPath, serviceProviderConfig, ""); } private void GivenThereIsAnUpstreamUrlPath(string upstreamUrlPath) diff --git a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs index 6b52a1c5..8802a5bc 100644 --- a/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs +++ b/test/Ocelot.UnitTests/Errors/ExceptionHandlerMiddlewareTests.cs @@ -9,17 +9,17 @@ namespace Ocelot.UnitTests.Errors using TestStack.BDDfy; using Xunit; using Microsoft.AspNetCore.Http; - using Ocelot.Configuration.Provider; using Moq; using Ocelot.Configuration; using Ocelot.Errors; using Ocelot.Infrastructure.RequestData; using Ocelot.Middleware; + using Ocelot.Configuration.Repository; public class ExceptionHandlerMiddlewareTests { bool _shouldThrowAnException; - private readonly Mock _provider; + private readonly Mock _configRepo; private readonly Mock _repo; private Mock _loggerFactory; private Mock _logger; @@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.Errors public ExceptionHandlerMiddlewareTests() { - _provider = new Mock(); + _configRepo = new Mock(); _repo = new Mock(); _downstreamContext = new DownstreamContext(new DefaultHttpContext()); _loggerFactory = new Mock(); @@ -45,13 +45,13 @@ namespace Ocelot.UnitTests.Errors context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK; }; - _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _provider.Object, _repo.Object); + _middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _configRepo.Object, _repo.Object); } [Fact] public void NoDownstreamException() { - var config = new OcelotConfiguration(null, null, null, null); + var config = new InternalConfiguration(null, null, null, null); this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) .And(_ => GivenTheConfigurationIs(config)) @@ -64,7 +64,7 @@ namespace Ocelot.UnitTests.Errors [Fact] public void DownstreamException() { - var config = new OcelotConfiguration(null, null, null, null); + var config = new InternalConfiguration(null, null, null, null); this.Given(_ => GivenAnExceptionWillBeThrownDownstream()) .And(_ => GivenTheConfigurationIs(config)) @@ -76,7 +76,7 @@ namespace Ocelot.UnitTests.Errors [Fact] public void ShouldSetRequestId() { - var config = new OcelotConfiguration(null, null, null, "requestidkey"); + var config = new InternalConfiguration(null, null, null, "requestidkey"); this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) .And(_ => GivenTheConfigurationIs(config)) @@ -89,7 +89,7 @@ namespace Ocelot.UnitTests.Errors [Fact] public void ShouldSetAspDotNetRequestId() { - var config = new OcelotConfiguration(null, null, null, null); + var config = new InternalConfiguration(null, null, null, null); this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream()) .And(_ => GivenTheConfigurationIs(config)) @@ -133,8 +133,8 @@ namespace Ocelot.UnitTests.Errors private void GivenTheConfigThrows() { var ex = new Exception("outer", new Exception("inner")); - _provider - .Setup(x => x.Get()).ThrowsAsync(ex); + _configRepo + .Setup(x => x.Get()).Throws(ex); } private void ThenAnExceptionIsThrown() @@ -144,9 +144,9 @@ namespace Ocelot.UnitTests.Errors private void GivenTheConfigReturnsError() { - var response = new Responses.ErrorResponse(new FakeError()); - _provider - .Setup(x => x.Get()).ReturnsAsync(response); + var response = new Responses.ErrorResponse(new FakeError()); + _configRepo + .Setup(x => x.Get()).Returns(response); } private void TheRequestIdIsSet(string key, string value) @@ -154,11 +154,11 @@ namespace Ocelot.UnitTests.Errors _repo.Verify(x => x.Add(key, value), Times.Once); } - private void GivenTheConfigurationIs(IOcelotConfiguration config) + private void GivenTheConfigurationIs(IInternalConfiguration config) { - var response = new Responses.OkResponse(config); - _provider - .Setup(x => x.Get()).ReturnsAsync(response); + var response = new Responses.OkResponse(config); + _configRepo + .Setup(x => x.Get()).Returns(response); } private void GivenAnExceptionWillNotBeThrownDownstream() diff --git a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj index 8df6245a..395dde67 100644 --- a/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj +++ b/test/Ocelot.UnitTests/Ocelot.UnitTests.csproj @@ -28,12 +28,6 @@ - - - PreserveNewest - - - diff --git a/test/Ocelot.UnitTests/configuration.json b/test/Ocelot.UnitTests/configuration.json deleted file mode 100755 index 618957b8..00000000 --- a/test/Ocelot.UnitTests/configuration.json +++ /dev/null @@ -1 +0,0 @@ -{"ReRoutes":[{"DownstreamPathTemplate":"/test/test/{test}","UpstreamPathTemplate":null,"UpstreamHttpMethod":null,"AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ApiName":null,"RequireHttps":false,"AllowedScopes":[],"ApiSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"https","DownstreamHost":"localhost","DownstreamPort":80,"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancer":null}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":"consul","Host":"blah","Port":198},"AdministrationPath":"testy"}} \ No newline at end of file diff --git a/test/Ocelot.UnitTests/idsrv3test.pfx b/test/Ocelot.UnitTests/idsrv3test.pfx deleted file mode 100644 index 0247dea0..00000000 Binary files a/test/Ocelot.UnitTests/idsrv3test.pfx and /dev/null differ