Skip to content

Commit

Permalink
#2084 Apply default config file paths in GetMergedOcelotJson when p…
Browse files Browse the repository at this point in the history
…roviding the `folder` argument of `AddOcelot` (#2120)

* Adding unit test first

* Fixing default global config file not being found in folder

* Adding PR trait to test

* Backing out whitespace changes

* Code review by @raman-m

* Create Configuration feature folder and move test classes

* Adjust namespace and review what we have

* Acceptance tests for #2084 user scenario

---------

Co-authored-by: Raman Maksimchuk <[email protected]>
  • Loading branch information
ben-bartholomew and raman-m authored Jul 16, 2024
1 parent 8c0180a commit d418b3f
Show file tree
Hide file tree
Showing 7 changed files with 364 additions and 263 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public static IConfigurationBuilder AddOcelot(this IConfigurationBuilder builder
string primaryConfigFile = null, string globalConfigFile = null, string environmentConfigFile = null, bool? optional = null, bool? reloadOnChange = null) // optional injections
{
var json = GetMergedOcelotJson(folder, env, null, primaryConfigFile, globalConfigFile, environmentConfigFile);
primaryConfigFile ??= Path.Join(folder, PrimaryConfigFile); // if not specified, merge & write back to the same folder
return ApplyMergeOcelotJsonOption(builder, mergeTo, json, primaryConfigFile, optional, reloadOnChange);
}

Expand All @@ -106,7 +107,7 @@ private static string GetMergedOcelotJson(string folder, IWebHostEnvironment env
FileConfiguration fileConfiguration = null, string primaryFile = null, string globalFile = null, string environmentFile = null)
{
var envName = string.IsNullOrEmpty(env?.EnvironmentName) ? "Development" : env.EnvironmentName;
environmentFile ??= string.Format(EnvironmentConfigFile, envName);
environmentFile ??= Path.Join(folder, string.Format(EnvironmentConfigFile, envName));
var reg = SubConfigRegex();
var environmentFileInfo = new FileInfo(environmentFile);
var files = new DirectoryInfo(folder)
Expand All @@ -117,8 +118,8 @@ private static string GetMergedOcelotJson(string folder, IWebHostEnvironment env
.ToArray();

fileConfiguration ??= new FileConfiguration();
primaryFile ??= PrimaryConfigFile;
globalFile ??= GlobalConfigFile;
primaryFile ??= Path.Join(folder, PrimaryConfigFile);
globalFile ??= Path.Join(folder, GlobalConfigFile);
var primaryFileInfo = new FileInfo(primaryFile);
var globalFileInfo = new FileInfo(globalFile);
foreach (var file in files)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,176 +7,176 @@
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using System.Text;

namespace Ocelot.AcceptanceTests
{
public class ConfigurationInConsulTests : IDisposable
{
private IHost _builder;
private readonly Steps _steps;
private IHost _fakeConsulBuilder;
private FileConfiguration _config;
private readonly List<ServiceEntry> _consulServices;

public ConfigurationInConsulTests()
{
_consulServices = new List<ServiceEntry>();
_steps = new Steps();
}

[Fact]
public void should_return_response_200_with_simple_url_when_using_jsonserialized_cache()
{
var consulPort = PortFinder.GetRandomPort();
var servicePort = PortFinder.GetRandomPort();

var configuration = new FileConfiguration
{
Routes = new List<FileRoute>
{
new()
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new()
{
Host = "localhost",
Port = servicePort,
},
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
},
},
GlobalConfiguration = new FileGlobalConfiguration
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
{
Scheme = "http",
Host = "localhost",
Port = consulPort,
},
},
};

var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";

this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, string.Empty))
.And(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{servicePort}", string.Empty, 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}

private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
{
_fakeConsulBuilder = Host.CreateDefaultBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{
var json = JsonConvert.SerializeObject(_config);
var bytes = Encoding.UTF8.GetBytes(json);
var base64 = Convert.ToBase64String(bytes);
var kvp = new FakeConsulGetResponse(base64);
await context.Response.WriteJsonAsync(new[] { kvp });
}
else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{
try
{
var reader = new StreamReader(context.Request.Body);
// Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
// var json = reader.ReadToEnd();
var json = await reader.ReadToEndAsync();
_config = JsonConvert.DeserializeObject<FileConfiguration>(json);
var response = JsonConvert.SerializeObject(true);
await context.Response.WriteAsync(response);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
else if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
{
await context.Response.WriteJsonAsync(_consulServices);
}
});
});
}).Build();

_fakeConsulBuilder.Start();
}

public class FakeConsulGetResponse
{
public FakeConsulGetResponse(string value)
{
Value = value;
}

public int CreateIndex => 100;
public int ModifyIndex => 200;
public int LockIndex => 200;
public string Key => "InternalConfiguration";
public int Flags => 0;
public string Value { get; }
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";
}

private void GivenThereIsAServiceRunningOn(string url, string basePath, int statusCode, string responseBody)
{
_builder = Host.CreateDefaultBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
});
})
.Build();

_builder.Start();
}

public void Dispose()
{
_builder?.Dispose();
_steps.Dispose();
}
}
}

namespace Ocelot.AcceptanceTests.Configuration
{
public class ConfigurationInConsulTests : IDisposable
{
private IHost _builder;
private readonly Steps _steps;
private IHost _fakeConsulBuilder;
private FileConfiguration _config;
private readonly List<ServiceEntry> _consulServices;

public ConfigurationInConsulTests()
{
_consulServices = new List<ServiceEntry>();
_steps = new Steps();
}

[Fact]
public void should_return_response_200_with_simple_url_when_using_jsonserialized_cache()
{
var consulPort = PortFinder.GetRandomPort();
var servicePort = PortFinder.GetRandomPort();

var configuration = new FileConfiguration
{
Routes = new List<FileRoute>
{
new()
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new()
{
Host = "localhost",
Port = servicePort,
},
},
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
},
},
GlobalConfiguration = new FileGlobalConfiguration
{
ServiceDiscoveryProvider = new FileServiceDiscoveryProvider
{
Scheme = "http",
Host = "localhost",
Port = consulPort,
},
},
};

var fakeConsulServiceDiscoveryUrl = $"http://localhost:{consulPort}";

this.Given(x => GivenThereIsAFakeConsulServiceDiscoveryProvider(fakeConsulServiceDiscoveryUrl, string.Empty))
.And(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{servicePort}", string.Empty, 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.BDDfy();
}

private void GivenThereIsAFakeConsulServiceDiscoveryProvider(string url, string serviceName)
{
_fakeConsulBuilder = Host.CreateDefaultBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
{
if (context.Request.Method.ToLower() == "get" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{
var json = JsonConvert.SerializeObject(_config);
var bytes = Encoding.UTF8.GetBytes(json);
var base64 = Convert.ToBase64String(bytes);
var kvp = new FakeConsulGetResponse(base64);
await context.Response.WriteJsonAsync(new[] { kvp });
}
else if (context.Request.Method.ToLower() == "put" && context.Request.Path.Value == "/v1/kv/InternalConfiguration")
{
try
{
var reader = new StreamReader(context.Request.Body);
// Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
// var json = reader.ReadToEnd();
var json = await reader.ReadToEndAsync();
_config = JsonConvert.DeserializeObject<FileConfiguration>(json);
var response = JsonConvert.SerializeObject(true);
await context.Response.WriteAsync(response);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
else if (context.Request.Path.Value == $"/v1/health/service/{serviceName}")
{
await context.Response.WriteJsonAsync(_consulServices);
}
});
});
}).Build();

_fakeConsulBuilder.Start();
}

public class FakeConsulGetResponse
{
public FakeConsulGetResponse(string value)
{
Value = value;
}

public int CreateIndex => 100;
public int ModifyIndex => 200;
public int LockIndex => 200;
public string Key => "InternalConfiguration";
public int Flags => 0;
public string Value { get; }
public string Session => "adf4238a-882b-9ddc-4a9d-5b6758e4159e";
}

private void GivenThereIsAServiceRunningOn(string url, string basePath, int statusCode, string responseBody)
{
_builder = Host.CreateDefaultBuilder()
.ConfigureWebHost(webBuilder =>
{
webBuilder.UseUrls(url)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseUrls(url)
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
});
});
})
.Build();

_builder.Start();
}

public void Dispose()
{
_builder?.Dispose();
_steps.Dispose();
}
}
}
Loading

0 comments on commit d418b3f

Please sign in to comment.