Функция Azure: обновление значения конфигурации вызывает исключение (источник конфигурации не зарегистрирован. Пожалуйста, зарегистрируйте его перед установкой значения.) - PullRequest
0 голосов
/ 15 апреля 2019

Я пытаюсь обновить значение одного из значений конфигурации в методе Configure (IWebJobsBuilder builder), он работает нормально при локальном запуске, но при развертывании в функции Azure выдает исключение.

Исключение:

Message:  A configuration source is not registered. Please register one before setting a value.

трассировка стека:

System.InvalidOperationException:
   at Microsoft.Extensions.Configuration.ConfigurationRoot.set_Item (Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.Extensions.Configuration.ChainedConfigurationProvider.Set (Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.Extensions.Configuration.ConfigurationRoot.set_Item (Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.Extensions.Configuration.ChainedConfigurationProvider.Set (Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at Microsoft.Extensions.Configuration.ConfigurationRoot.set_Item (Microsoft.Extensions.Configuration, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
   at ConvAi.BfChannel.BotManagementService.WebJobsExtensionStartup.Configure (ConvAi.BfChannel.BotManagementService, Version=0.0.0.0, Culture=neutral, PublicKeyToken=nullConvAi.BfChannel.BotManagementService, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null: E:\Git\skyman - Copy\conversational-ai\src\ConvAi.BfChannel.BotManagementService\WebJobsExtensionStartup.csConvAi.BfChannel.BotManagementService, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null: 99)

Я зарегистрировал поставщиков конфигурации в приложении insights и вижу, что зарегистрировано 3 поставщика конфигурации.

1.  Microsoft.Extensions.Configuration.ChainedConfigurationProvider
2.  Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider
3.  Microsoft.Extensions.Configuration.Memory.MemoryConfigurationProvider

Вот проблемный код:

config["BotManagementServiceBusConnectionString"] =
                    config[serviceBusConnectionStringKey].Remove(
                        config[serviceBusConnectionStringKey].Length - ";EntityPath=Topic1".Length);

Вот полный код:

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="WebJobsExtensionStartup.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//  --------------------------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using Intercom.Helpers;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

[assembly: WebJobsStartup(typeof(ConvAi.BfChannel.BotManagementService.WebJobsExtensionStartup), "Web Jobs Extension")]
namespace ConvAi.BfChannel.BotManagementService
{
    /// <summary>
    /// WebJobsExtensionStartup
    /// </summary>
    public class WebJobsExtensionStartup : IWebJobsStartup
    {
        /// <summary>
        /// AzureServiceTokenProvider which is used for requesting identity token.
        /// </summary>
        public static AzureServiceTokenProvider AzureServiceTokenProvider { get; set; }

        /// <summary>
        /// Configure services.
        /// </summary>
        /// <param name="builder">WebJob Builder</param>
        public void Configure(IWebJobsBuilder builder)
        {
            try
            {
                bool isLocal = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"));

                // Gets the default configuration
                var serviceConfig = builder.Services.FirstOrDefault(s => s.ServiceType.Equals(typeof(IConfiguration)));
                var rootConfig = (IConfiguration)serviceConfig.ImplementationInstance;
                var keyVault = rootConfig["BFSpeechKeyVault"];
                var serviceBusConnectionStringKey = rootConfig["BotManagementServiceBusConnectionStringKey"];

                if (isLocal)
                {
                    // Use developers's idenity.
                    AzureServiceTokenProvider = new AzureServiceTokenProvider();
                }
                else
                {
                    // Use azure function's managed idenity.
                    var msiClientId = rootConfig["MSI_ClientId"];
                    AzureServiceTokenProvider = new AzureServiceTokenProvider(connectionString: $"RunAs=App;AppId={msiClientId}");
                }

                var keyVaultClient = new KeyVaultClient(
                    new KeyVaultClient.AuthenticationCallback(
                        AzureServiceTokenProvider.KeyVaultTokenCallback));

                var config = new ConfigurationBuilder()
                    .AddConfiguration(rootConfig).AddAzureKeyVault(
                    keyVault,
                    keyVaultClient,
                    new DefaultKeyVaultSecretManager())
                    .AddInMemoryCollection()
                    .Build();

                config["BotManagementServiceBusConnectionString"] =
                    config[serviceBusConnectionStringKey].Remove(
                        config[serviceBusConnectionStringKey].Length - ";EntityPath=Topic1".Length);

                // Replace the existing config
                builder.Services.AddSingleton<IConfiguration>(config);
            }
            catch (Exception ex)
            {
                AppInsights.TrackException(
                    ex,
                    "Failed to start Bot management service",
                    "Sender".PairWith(this.GetType().FullName));
            }
        }
    }
}

Может кто-нибудь помочь мне разобраться, что происходит?

1 Ответ

0 голосов
/ 21 апреля 2019

Мне удалось решить проблему, добавив значения в провайдер памяти.

Config [“”] = оператор значения пытается добавить / обновить конфигурацию для каждого провайдера конфигурации, и я мог видеть, чтоУ ChainedConfigProvider есть несколько провайдеров в цепочке, которые не зарегистрированы, если они не используются в коде.ChainedConfigProvider имеет различный набор поставщиков при локальном использовании и при использовании в Azure.Из-за чего оператор не выполняется с исключением в Azure.

Вот окончательный код:

       bool isLocal = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"));



        // Gets the default configuration

        var serviceConfig = builder.Services.FirstOrDefault(s => s.ServiceType.Equals(typeof(IConfiguration)));

        var rootConfig = (IConfiguration)serviceConfig.ImplementationInstance;

        var keyVault = rootConfig["BFSpeechKeyVault"];

        var serviceBusConnectionStringKey = rootConfig["BotManagementServiceBusConnectionStringKey"];



        if (isLocal)

        {

            TelemetryConfiguration.Active.DisableTelemetry = true;



            // Use developers's idenity.

            AzureServiceTokenProvider = new AzureServiceTokenProvider();

        }

        else

        {

            // Use azure function's managed idenity.

            var msiClientId = rootConfig["MSI_ClientId"];



            AzureServiceTokenProvider = new AzureServiceTokenProvider(connectionString: $"RunAs=App;AppId={msiClientId}");

        }



        var keyVaultClient = new KeyVaultClient(

            new KeyVaultClient.AuthenticationCallback(

                AzureServiceTokenProvider.KeyVaultTokenCallback));



        var keyVaultConfig = new ConfigurationBuilder()

            .AddAzureKeyVault(

            keyVault,

            keyVaultClient,

            new DefaultKeyVaultSecretManager())

            .Build();



        var botManagementServiceBusConnectionString = Regex.Replace(keyVaultConfig[serviceBusConnectionStringKey], @";EntityPath=Topic1$", string.Empty, RegexOptions.IgnoreCase);



        var config = new ConfigurationBuilder()

            .AddConfiguration(rootConfig)

            .AddInMemoryCollection(

                new Dictionary<string, string>

                {

                    {

                        "BotManagementServiceBusConnectionString",

                        botManagementServiceBusConnectionString

                    }

                })

            .Build();
...