How to work with multiple configuration files per microservice? #1859
-
Hi, Can you please provide a working code that can read multiple route configurations for each microservice and can run both. In my case, I can only access the last added route configuration. Here is my program.cs file using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using System.IO;
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
.Build()
.Run();
}
static IWebHostEnvironment _hostingContextEnvironment = null;
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
_hostingContextEnvironment = hostingContext.HostingEnvironment;
config
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile("ocelot.json", false, true)
.AddJsonFile("student.ocelot.Development.json", false, true)
.AddJsonFile("teacher.ocelot.Development.json", false, true)
.AddEnvironmentVariables();
})
.ConfigureServices(s =>
{
s.AddOcelot();
})
.Configure(app =>
{
app.UseOcelot().Wait();
});
} Originally posted by @sachinvaid1604 in #1186 (comment) |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 6 replies
-
Sachin, fork Ocelot repo first to look into the Ocelot code! After forking Ocelot you will figure out that /// <summary>
/// Adds a JSON configuration source to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="provider">The <see cref="IFileProvider"/> to use to access the file.</param>
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="optional">Whether the file is optional.</param>
/// <param name="reloadOnChange">Whether the configuration should be reloaded if the file changes.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, IFileProvider? provider, string path, bool optional, bool reloadOnChange)
{
ThrowHelper.ThrowIfNull(builder);
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException(SR.Error_InvalidFilePath, nameof(path));
}
return builder.AddJsonFile(s =>
{
s.FileProvider = provider;
s.Path = path;
s.Optional = optional;
s.ReloadOnChange = reloadOnChange;
s.ResolveFileProvider();
});
} I have no idea how inner MS implementation merges config JSON. If you call .AddJsonFile("student.ocelot.Development.json", false, true)
.AddJsonFile("teacher.ocelot.Development.json", false, true) and they describe the same routes, seems the second file will overwrite the routes from the first one. |
Beta Was this translation helpful? Give feedback.
-
You described exactly the same user scenario of #296 for merging multiple files of the same environment. You have to read this Ocelot doc: Merging Configuration Files So, you need this setup: .ConfigureAppConfiguration((hostingContext, config) =>
{
config
// ...
.AddOcelot(hostingContext.HostingEnvironment)
.AddEnvironmentVariables();
}) |
Beta Was this translation helpful? Give feedback.
-
@raman-m Thanks a lot for guiding me in the right direction. I was using the wrong convention of the file names as it never matches with what Ocelot looks for. The configuration files should always start with ocelot along with the environment name. Thank you for showing me the path to internally go into the working of Ocelot's AddOcelot method. Its working perfectly fine now. |
Beta Was this translation helpful? Give feedback.
-
There is a flaw in the Ocelot's AddOcelot method, it only traverse the current directory, rather than subdirectories, so It's better to write your own extension method that can traverse subdirectories so as to keep the files segregated in their respective folders and provide better management. Also, in my case I renamed the configuration files as follow. |
Beta Was this translation helpful? Give feedback.
-
There is a flaw in the Ocelot's AddOcelot method, it only traverse the current directory, rather than subdirectories, so It's better to write your own extension method that can traverse subdirectories so as to keep the files segregated in their respective folders and provide better management. Also, in my case I renamed the configuration files as follow. |
Beta Was this translation helpful? Give feedback.
-
private static FileConfiguration GetOcelotFiles(string folder, IWebHostEnvironment env)
{
string excludeConfigName = ((env != null && env.EnvironmentName != null) ? ("ocelot." + env.EnvironmentName + ".json") : string.Empty);
Regex reg = SubConfigRegex();
FileInfo[] array = (from fi in new DirectoryInfo(folder).EnumerateFiles("*", SearchOption.AllDirectories)
where reg.IsMatch(fi.Name) && fi.Name != excludeConfigName
select fi).ToArray();
FileConfiguration fileConfiguration = new FileConfiguration();
FileInfo[] array2 = array;
foreach (FileInfo fileInfo in array2)
{
if (array.Length <= 1 || !fileInfo.Name.Equals("ocelot.json", StringComparison.OrdinalIgnoreCase))
{
FileConfiguration fileConfiguration2 = JsonConvert.DeserializeObject<FileConfiguration>(File.ReadAllText(fileInfo.FullName));
if (fileInfo.Name.Equals("ocelot.global.json", StringComparison.OrdinalIgnoreCase))
{
fileConfiguration.GlobalConfiguration = fileConfiguration2.GlobalConfiguration;
}
fileConfiguration.Aggregates.AddRange(fileConfiguration2.Aggregates);
fileConfiguration.Routes.AddRange(fileConfiguration2.Routes);
}
}
return fileConfiguration;
} This is the utility method I created and just call the |
Beta Was this translation helpful? Give feedback.
You described exactly the same user scenario of #296 for merging multiple files of the same environment.
You have to read this Ocelot doc: Merging Configuration Files
So, you need this setup: