ThreeMammals / Ocelot

.NET API Gateway
https://www.nuget.org/packages/Ocelot
MIT License
8.31k stars 1.63k forks source link

How to work with multiple configuration files per microservice? #1858

Closed sachinvaid1604 closed 8 months ago

sachinvaid1604 commented 8 months ago
          > Ok guys, so I have found out what was causing the strange behaviour.

It was the folder structure that we are using in Kubernetes for our configuration files.

Generally placing configuration files in the folder structure described below will cause described issue.

This could be written in the documentation as a note.

Folder structure: etc/config/

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();
            });
}

image

Originally posted by @sachinvaid1604 in https://github.com/ThreeMammals/Ocelot/issues/1186#issuecomment-1859061387

raman-m commented 8 months ago

Sachin, fork Ocelot repo first to look into the Ocelot code!

After forking Ocelot you will figure out that AddJsonFile method is a part of JsonConfigurationExtensions class from Microsoft.Extensions.Configuration namespace! If you press F12 key multiple times, you will get to this Microsoft ASP.NET implementation:

        /// <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. Microsoft classes don't merge!