web-dev-qa-db-fra.com

Variables d'environnement AWS Elastic Beanstalk dans ASP.NET Core 1.0

Comment puis-je obtenir des variables d'environnement de beanstalk élastique dans une application mvc core asp.net? J'ai ajouté un dossier .ebextensions contenant le fichier app.config avec les éléments suivants:

option_settings:
- option_name: HelloWorld
  value: placeholder

- option_name: ASPNETCORE_ENVIRONMENT
  value: placeholder

Le dossier .ebextensions est inclus dans le package de publication.

Lors du déploiement, les deux variables sont visibles dans la console aws elasticbeanstalk dans Configuration> Configuration logicielle> Variables d'environnement

Cependant, lorsque j'essaie de lire les variables dans l'application, aucune des options ci-dessous ne fonctionne:

Environment.GetEnvironmentVariable("HelloWorld") // In controller
Configuration["HelloWorld"] // In startup.cs

Des idées sur ce qui pourrait me manquer? Merci.

33
Girish

A eu le même problème et vient de recevoir une réponse du support AWS à propos de ce problème. Apparemment, les variables d'environnement ne sont pas correctement injectées dans les applications ASP.NET Core dans le beanstalk élastique.

Autant que je sache, ils travaillent pour résoudre le problème.

La solution consiste à analyser C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration dans le générateur de configuration. Ce fichier fait partie de votre environnement élastique beanstalk et doit être accessible lors du déploiement de votre projet.

Ajoutez d'abord le fichier:

var builder = new ConfigurationBuilder()
    .SetBasePath("C:\\Program Files\\Amazon\\ElasticBeanstalk\\config")
    .AddJsonFile("containerconfiguration", optional: true, reloadOnChange: true);

Accédez ensuite aux valeurs:

var env = Configuration.GetSection("iis:env").GetChildren();

foreach (var envKeyValue in env)
{
    var splitKeyValue = envKeyValue.Value.Split('=');
    var envKey = splitKeyValue[0];
    var envValue = splitKeyValue[1];
    if (envKey == "HelloWorld")
    {
        // use envValue here
    }
}

Gracieuseté de G.P. d'Amazon Web Services

23
user7077512

Je viens d'implémenter une solution légèrement différente qui injecte les variables d'environnement beanstalk dans le programme afin que vous puissiez y accéder par Environment.GetEnvironmentVariable():

private static void SetEbConfig()
{
    var tempConfigBuilder = new ConfigurationBuilder();

    tempConfigBuilder.AddJsonFile(
        @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
        optional: true,
        reloadOnChange: true
    );

    var configuration = tempConfigBuilder.Build();

    var ebEnv =
        configuration.GetSection("iis:env")
            .GetChildren()
            .Select(pair => pair.Value.Split(new[] { '=' }, 2))
            .ToDictionary(keypair => keypair[0], keypair => keypair[1]);

    foreach (var keyVal in ebEnv)
    {
        Environment.SetEnvironmentVariable(keyVal.Key, keyVal.Value);
    }
}

Appelez simplement SetEbConfig(); avant de construire votre hébergeur. Avec cette solution, AWS SDK lit également correctement ses paramètres tels que AWS_ACCESS_KEY_ID.

30
Sebastian

J'ai implémenté l'autre réponse pour créer une solution de contournement pratique pour charger les propriétés d'environnement depuis Elastic Beanstalk directement dans la configuration de votre application ASP.NET Core.

Pour ASP.NET Core 2.0 - modifiez votre Program.cs

Notez que cette génération WebHost a été prise à partir du code source de WebHostBuilder.CreateDefaultBuilder ()

https://github.com/aspnet/MetaPackages/blob/dev/src/Microsoft.AspNetCore/WebHost.cs

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace NightSpotAdm
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args)
        {
            // TEMP CONFIG BUILDER TO GET THE VALUES IN THE ELASTIC BEANSTALK CONFIG
            IConfigurationBuilder tempConfigBuilder = new ConfigurationBuilder();

            tempConfigBuilder.AddJsonFile(
                @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
                optional: true,
                reloadOnChange: true
            );

            IConfigurationRoot tempConfig = tempConfigBuilder.Build();

            Dictionary<string, string> ebConfig = ElasticBeanstalk.GetConfig(tempConfig);

            // START WEB Host BUILDER
            IWebHostBuilder builder = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory());

            // CHECK IF EBCONFIG HAS ENVIRONMENT KEY IN IT
            // IF SO THEN CHANGE THE BUILDERS ENVIRONMENT
            const string envKey = "ASPNETCORE_ENVIRONMENT";

            if (ebConfig.ContainsKey(envKey))
            {
                string ebEnvironment = ebConfig[envKey];
                builder.UseEnvironment(ebEnvironment);
            }

            // CONTINUE WITH WEB Host BUILDER AS NORMAL
            builder.ConfigureAppConfiguration((hostingContext, config) =>
                {
                    IHostingEnvironment env = hostingContext.HostingEnvironment;

                    // ADD THE ELASTIC BEANSTALK CONFIG DICTIONARY
                    config.AddJsonFile(
                            "appsettings.json",
                            optional: true,
                            reloadOnChange: true
                        )
                        .AddJsonFile(
                            $"appsettings.{env.EnvironmentName}.json",
                            optional: true,
                            reloadOnChange: true
                        )
                        .AddInMemoryCollection(ebConfig);

                    if (env.IsDevelopment())
                    {
                        Assembly appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
                        if (appAssembly != null)
                        {
                            config.AddUserSecrets(appAssembly, optional: true);
                        }
                    }

                    config.AddEnvironmentVariables();

                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                .ConfigureLogging((hostingContext, logging) =>
                {
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                    logging.AddDebug();
                })
                .UseIISIntegration()
                .UseDefaultServiceProvider(
                    (context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); })
                .ConfigureServices(
                    services =>
                    {
                        services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
                    });

            return builder.UseStartup<Startup>().Build();
        }
    }

    public static class ElasticBeanstalk
    {
        public static Dictionary<string, string> GetConfig(IConfiguration configuration)
        {
            return
                configuration.GetSection("iis:env")
                    .GetChildren()
                    .Select(pair => pair.Value.Split(new[] { '=' }, 2))
                    .ToDictionary(keypair => keypair[0], keypair => keypair[1]);
        }
    }
}

Pour ASP.NET Core 1.0

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddJsonFile(@"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();

        var config = builder.Build();

        builder.AddInMemoryCollection(GetEbConfig(config));

        Configuration = builder.Build();
    }

    private static Dictionary<string, string> GetEbConfig(IConfiguration configuration)
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();

        foreach (IConfigurationSection pair in configuration.GetSection("iis:env").GetChildren())
        {
            string[] keypair = pair.Value.Split(new [] {'='}, 2);
            dict.Add(keypair[0], keypair[1]);
        }

        return dict;
    }
7
ArcadeRenegade

Au lieu d'avoir à analyser le containerconfiguration, vous pouvez utiliser les options ebextensions pour définir la variable dans le cadre de votre processus de déploiement:

commands:
  set_environment: 
    command: setx ASPNETCORE_ENVIRONMENT "Development" /M

Cela définira une variable d'environnement global dans le cadre du déploiement de votre application. Ce cas d'utilisation variable est officiellement pris en charge et documenté par Microsoft.

Après avoir déployé votre application, vous pouvez vérifier que le paramètre est correctement défini dans l'instance EC2:

environment variable

4
Justin Helgerson

La solution ci-dessus ne m'a pas aidé à charger le fichier de configuration en fonction des paramètres de l'environnement. Voici donc ma solution AWS Elastic BeansTalk "hack"

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{GetEnvVariableAWSBeansTalkHack(env)}.json", optional: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    private static string GetEnvVariableAWSBeansTalkHack(IHostingEnvironment env)
    {
        var config = new ConfigurationBuilder()
           .AddJsonFile(@"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration", optional: true, reloadOnChange: true).Build();

        Dictionary<string, string> dict = new Dictionary<string, string>();
        foreach (IConfigurationSection pair in config.GetSection("iis:env").GetChildren())
        {
            string[] keypair = pair.Value.Split(new[] { '=' }, 2);
            dict.Add(keypair[0], keypair[1]);
        }

        return dict.ContainsKey("ASPNETCORE_ENVIRONMENT") 
                ? dict["ASPNETCORE_ENVIRONMENT"] 
                : env.EnvironmentName;
    }
2
dmitril

. NET Core 2 + posrgresql RDS

Suite à la grande réponse de @ sebastian ci-dessus, j'ai trouvé que les paramètres se trouvaient dans une partie différente du fichier, à savoir. plugins:rds:env.

De plus, il n'était pas nécessaire de diviser le =, donc le code d'analyse que j'ai est:

private static void SetEbConfig()
        {
            var tempConfigBuilder = new ConfigurationBuilder();

            tempConfigBuilder.AddJsonFile(
                @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
                optional: true,
                reloadOnChange: true
            );

            var configuration = tempConfigBuilder.Build();

            var ebEnv = configuration.GetSection("plugins:rds:env")
                                        .GetChildren()
                                        .ToDictionary(child => child.Key, child => child.Value);

            foreach (var keyVal in ebEnv)
            {
                Environment.SetEnvironmentVariable(keyVal.Key, keyVal.Value);
            }
        }

Le JSON pertinent (et expurgé ;-)) est le suivant:

{
    "plugins": {
        "rds": {
            "Description": "RDS Environment variables",
            "env": {
                "RDS_PORT": "....",
                "RDS_HOSTNAME": "....",
                "RDS_USERNAME": "....",
                "RDS_DB_NAME": "....",
                "RDS_PASSWORD": "...."
            }
        }
    }
}

(Cette réponse est séparée car je n'ai pas de représentant pour commenter ...)

1
mrblewog

Vous pouvez créer une implémentation de Microsoft.Extensions.Configuration.

Également disponible sur https://Gist.github.com/skarllot/11e94ed8901a9ddabdf05c0e5c08dbc5 .

using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Linq;

namespace Microsoft.Extensions.Configuration.AWS
{
    public class AmazonEBConfigurationProvider : ConfigurationProvider
    {
        private const string ConfigurationFilename = @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration";

        public override void Load()
        {
            if (!File.Exists(ConfigurationFilename))
                return;

            string configJson;
            try
            {
                configJson = File.ReadAllText(ConfigurationFilename);
            }
            catch
            {
                return;
            }

            var config = JObject.Parse(configJson);
            var env = (JArray)config["iis"]["env"];

            if (env.Count == 0)
                return;

            foreach (var item in env.Select(i => (string)i))
            {
                int eqIndex = item.IndexOf('=');
                Data[item.Substring(0, eqIndex)] = item.Substring(eqIndex + 1);
            }
        }
    }

    public class AmazonEBConfigurationSource : IConfigurationSource
    {
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new AmazonEBConfigurationProvider();
        }
    }

    public static class AmazonEBExtensions
    {
        public static IConfigurationBuilder AddAmazonElasticBeanstalk(this IConfigurationBuilder configurationBuilder)
        {
            configurationBuilder.Add(new AmazonEBConfigurationSource());
            return configurationBuilder;
        }
    }
}

Utilisez ensuite avec votre ConfigurationBuilder:

var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", true, true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
    .AddAmazonElasticBeanstalk()    // <-- Merge with other sources
    .AddEnvironmentVariables();
0
Fabricio Godoy