5
votes

Comment modifier IConfiguration injecté nativement dans Azure Functions

Nous devons ajouter des fournisseurs de configuration à l'IConfiguration native fournie aux fonctions Azure de manière native. À l' heure actuelle , nous sommes complètement remplaçons avec notre IConfiguration de mesure utilisant le code suivant:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        ...

        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddAzureKeyVault(...)
            .AddJsonFile("local.settings.json", true, true)
            .AddEnvironmentVariables()
            .Build();

        builder.Services.AddSingleton<IConfiguration>(configuration);

        builder.Services.AddSingleton<IMyService, MyService>();
    }
}

Un certain contexte

MyService a besoin dans son constructeur des valeurs du fournisseur KeyVault et également d'autres instances comme Application Insights, etc. Si nous laissons l'IConfiguration par défaut, il n'a pas les valeurs KeyVault. Si nous créons l'instance MyService avec une fabrique, nous devons fournir manuellement l'instance App Insights, etc. Remplacement actuel des compilations IConfiguration et exécution de la fonction. Mais cela rompt un autre comportement par défaut comme ne pas prendre les configurations de host.json (nous essayons de configurer le déclencheur de file d'attente). L'utilisation de IConfiguration par défaut lit correctement les paramètres de host.json.


7 commentaires

La question ici n'est pas du tout claire.


@Tom Au lieu de remplacer, nous devons modifier l'IConfiguration par défaut.


docs.microsoft.com/en-us/azure/azure-app-configuration/...


@ user33276346 Jetez un œil à ce stackoverflow.com/a/60078802/5233410


@Aluan 438 $ par an, n'y a-t-il pas une solution de contournement de codage?


@Nkosi J'ai essayé votre solution, mais comme le mentionne Anthony Brenelière, elle remplace quelque chose dans le runtime de la fonction. Le problème est que la solution Anthony Brenelière ne s'adapte pas à nos besoins car nous devons passer la configuration d'origine ainsi que notre configuration particulière (fichiers, KeyVault, etc.) sans modifier le comportement normal de Function. Par exemple, nous devons modifier le nombre de tentatives pour un déclencheur de file d'attente en le définissant dans host.json. Si nous laissons la configuration injectée par défaut, cela fonctionne. Mais si nous appliquons votre solution ou la nôtre, elle ignore les paramètres de nouvelle tentative et suit le comportement par défaut.


@Nkosi la configuration host.json dont je parle: "extensions": {"queues": {"maxDequeueCount": 3, "visibilitéTimeout": "00:00:30"}} Tiré de docs.microsoft.com/ fr-fr / azure / azure-functions /…


3 Réponses :


1
votes

Option 1: apportez la configuration de base avant les autres fournisseurs de configuration
{
    "DbConfig": { "SuperSecretValue": "abc123" }
}

Option 2: Rendez vos dépendances personnalisées plus fines et utilisez IOptions<T>

Au lieu de remplacer l'instance injectée d'IConfiguration ou d'utiliser l'option 1 ci-dessus, rendez vos services en aval dépendants d'un IOptions<T> . Je pense que c'est le meilleur modèle, car vous pouvez diviser votre configuration en petits segments en fonction de vos besoins et faire en sorte que vos services prennent des dépendances plus ciblées.

public class MyService : IMyService
{
    private MyDbConfig _dbConfig;
    public MyService(IOptions<MyDbConfig> myDbConfig)
    {
        _dbConfig = myDbConfig.Value;
    }
}

Dans ce scénario, MyDbConfig est juste un POCO avec des propriétés pour héberger votre configuration. Votre classe de service prend la dépendance sur IOptions<MyDbConfig> :

var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddAzureKeyVault(...)
            .AddJsonFile("local.settings.json", true, true)
            .AddEnvironmentVariables()
            .Build();

// don't re-bind IConfiguration
// builder.Services.AddSingleton<IConfiguration>(configuration);

// instead, bind sections specific to what services may need
builder.Services.Configure<MyDbConfig>(config.GetSection("DbConfig"));

Dans les configurations basées sur JSON, vous incluez "DbConfig" (ou tout autre argument que vous fournissez à GetSection ) en tant qu'objet JSON de niveau supérieur, avec vos valeurs de configuration en tant que propriétés dans cet objet:

// ...

var baseConfig = builder.Services.BuildServiceProvider().GetService<IConfiguration>();

var configuration = new ConfigurationBuilder()
    .AddConfiguration(baseConfig)
    .SetBasePath(Directory.GetCurrentDirectory())
    .AddAzureKeyVault(...)
    .AddJsonFile("local.settings.json", true, true)
    .AddEnvironmentVariables()
    .Build();

// ...

Dans KeyVault, vous utilisez -- pour indiquer le modèle d'imbrication, avec un nom secret tel que DbConfig--SuperSecretValue .


0 commentaires

6
votes

Il y a quelques commentaires sur l'utilisation des fonctions Azure .NET Core:

  1. Lors de l'exécution locale, local.settings.json est chargé pour vous par défaut par le framework.
  2. Vous devez éviter de lire les valeurs de configuration à partir de appsettings.json ou d'autres fichiers, en particulier lors de l'exécution sur le plan de consommation. Documentation sur les fonctions
  3. En général, vous devez vous abstenir de passer autour de l'objet IConfiguration . Comme @Dusty l'a mentionné, la méthode IOptions consiste à utiliser le modèle IOptions .
  4. Si vous essayez de lire des valeurs à partir d'Azure Key Vault, vous n'avez pas besoin d'ajouter AddAzureKeyVault() car vous pouvez et devez le configurer dans le portail azure à l'aide des références Azure Key Vault. Documents sur Key Vault . En faisant cela, le mécanisme de configuration de la fonction azure ne sait pas / ne se soucie pas où il s'exécute, si vous l'exécutez localement, il se chargera à partir de local.settings.json, s'il est déployé, il obtiendra les valeurs de la configuration de l'application Azure et si vous avez besoin de l'intégration d'Azure Key Vault, tout est effectué via les références Azure Key Vault.
  5. Je pense qu'il est également essentiel ici que la configuration des fonctions Azure ne soit pas la même qu'une application .NET traditionnelle qui utilise appsettings.json.
  6. La configuration de l'application Azure Functions peut devenir fastidieuse, car vous devez ajouter des paramètres un par un. Nous avons résolu ce problème en utilisant Azure App Configuration. Vous pouvez également le connecter à Azure Key Vault.
  7. Application Insights est ajouté automatiquement par Azure Functions. Docs

Cela étant dit, vous pouvez toujours accomplir ce que vous voulez même si ce n'est pas recommandé en procédant comme suit. Gardez à l'esprit que vous pouvez également ajouter les références de coffre-fort de clés dans le code suivant par AddAzureKeyVault()

var configurationBuilder = new ConfigurationBuilder();
var descriptor = builder.Services.FirstOrDefault(d => d.ServiceType == typeof(IConfiguration));
if (descriptor?.ImplementationInstance is IConfiguration configRoot)
{
    configurationBuilder.AddConfiguration(configRoot);
}

// Conventions are different between Azure and Local Development and API
// https://github.com/Azure/Azure-Functions/issues/717
// Environment.CurrentDirectory doesn't cut it in the cloud.
// https://stackoverflow.com/questions/55616798/executioncontext-in-azure-function-iwebjobsstartup-implementation
var localRoot = Environment.GetEnvironmentVariable("AzureWebJobsScriptRoot");
var actualRoot = $"{Environment.GetEnvironmentVariable("HOME")}/site/wwwroot";
var basePath = localRoot ?? actualRoot;
var configuration = configurationBuilder
    .SetBasePath(basePath)
    .AddJsonFile("local.settings.json", optional: true, reloadOnChange: false)
    .AddEnvironmentVariables()
    .Build();

builder.Services.Replace(ServiceDescriptor.Singleton(typeof(IConfiguration), configuration));

Faites-moi savoir si vous avez besoin de plus de commentaires / clarifications à ce sujet et je mettrai à jour ma réponse en conséquence.


2 commentaires

Excellente réponse. Bien expliqué, fournit toutes les options, des liens vers la documentation et donne même un exemple de code. Voudrais entendre OP et confirmer que cela fonctionne.


@TroyWitthoeft Merci! Je peux confirmer que cela fonctionne bien. Il y a quelques semaines, il y a quelques semaines dans le trou du lapin de configuration Azure Functions :)



1
votes

Une solution plus simple consisterait à remplacer la méthode ConfigureAppConfiguration dans votre classe FunctionStartup ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources ).

L'exemple suivant va encore plus loin dans celui fourni dans la documentation en ajoutant des secrets utilisateur.

public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
    FunctionsHostBuilderContext context = builder.GetContext();

    builder.ConfigurationBuilder
        .SetBasePath(context.ApplicationRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
        .AddJsonFile($"appsettings.{context.EnvironmentName}.json", optional: true, reloadOnChange: false)
        .AddUserSecrets(Assembly.GetExecutingAssembly(), true, true)
        .AddEnvironmentVariables();
}

Par défaut, les fichiers de configuration tels que appsettings.json ne sont pas automatiquement copiés dans le dossier de sortie Azure Function. Assurez-vous de consulter la documentation ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection#customizing-configuration-sources ) pour les modifications apportées à votre fichier .csproj . Notez également qu'en raison de la façon dont la méthode ajoute les fournisseurs existants, il est nécessaire de toujours terminer par .AddEnvironmentVariables () .

Une discussion plus approfondie sur la configuration dans une fonction Azure est disponible sur Utilisation de ConfigurationBuilder dans FunctionsStartup


0 commentaires