Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

Azure App Configuration を試してみよう on Azure Functions

$
0
0

アプリ設定を WebApps の構成のアプリケーション設定とは別に管理できる App Configuration を試してみました!

docs.microsoft.com

最近は ARM Template 書いてみるのがブームなので、以下のように ARM Template 作って下準備しました。

{"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {"appName": {"type": "string"
        }},
    "variables": {"storageAccountName": "[concat(parameters('appName'), 'storage')]",
        "storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
        "appInsightsName": "[concat(parameters('appName'), '-insights')]",
        "functionAppName": "[concat(parameters('appName'), '-func')]",
        "hostingPlanName": "[concat(parameters('appName'), '-plan')]",
        "appConfigurationName": "[concat(parameters('appName'), 'config')]",
        "appConfigurationId": "[concat(resourceGroup().id,'/providers/','Microsoft.AppConfiguration/configurationStores/', variables('appConfigurationName'))]"
    },
    "resources": [{"type": "Microsoft.Storage/storageAccounts",
            "name": "[variables('storageAccountName')]",
            "apiVersion": "2019-04-01",
            "location": "[resourceGroup().location]",
            "kind": "StorageV2",
            "sku": {"name": "Standard_LRS"
            }},
        {"apiVersion": "2015-05-01",
            "name": "[variables('appInsightsName')]",
            "type": "Microsoft.Insights/components",
            "kind": "web",
            "location": "[resourceGroup().location]",
            "tags": {"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('functionAppName'))]": "Resource"
            },
            "properties": {"Application_Type": "web",
                "ApplicationId": "[variables('appInsightsName')]"
            }},
        {"type": "Microsoft.Web/serverfarms",
            "apiVersion": "2016-09-01",
            "name": "[variables('hostingPlanName')]",
            "location": "[resourceGroup().location]",
            "properties": {"name": "[variables('hostingPlanName')]",
                "computeMode": "Dynamic"
            },
            "sku": {"name": "Y1",
                "tier": "Dynamic",
                "size": "Y1",
                "family": "Y",
                "capacity": 0}},
        {"apiVersion": "2016-08-01",
            "type": "Microsoft.Web/sites",
            "name": "[variables('functionAppName')]",
            "location": "[resourceGroup().location]",
            "kind": "functionapp",
            "dependsOn": ["[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
            ],
            "properties": {"siteConfig": {"appSettings": [{"name": "AzureWebJobsStorage",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
                        },
                        {"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
                        },
                        {"name": "WEBSITE_CONTENTSHARE",
                            "value": "[toLower(variables('functionAppName'))]"
                        },
                        {"name": "FUNCTIONS_WORKER_RUNTIME",
                            "value": "dotnet"
                        },
                        {"name": "FUNCTIONS_EXTENSION_VERSION",
                            "value": "~3"
                        },
                        {"name": "WEBSITE_RUN_FROM_PACKAGE",
                            "value": 1},
                        {"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                            "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2015-05-01').InstrumentationKey]"
                        },
                        {"name": "AppConfigurationConnectionString",
                            "value": "[ListKeys(variables('appConfigurationId'), '2019-10-01').value[2].connectionString]"
                        }]}}},
        {"name": "[variables('appConfigurationName')]",
            "type": "Microsoft.AppConfiguration/configurationStores",
            "apiVersion": "2019-10-01",
            "location": "[resourceGroup().location]",
            "properties": {},
            "sku": {"name": "standard"
            }}],
    "outputs": {},
    "functions": []}

App Configuration の接続文字列は ListKeys 関数でプライマリー読み書き、セカンダリー読み書き、プライマリー読み込み専用、セカンダリー読み込み専用の順番で入った値が返ってくるので 3 番目の要素の connectionString で取れます。

App Configuratoin の ARM Template は以下のドキュメントを参考にしました。

docs.microsoft.com

接続文字列をとってくる関数は、以下のドキュメントを見て ListKeys なんだと確認しました。

docs.microsoft.com

とりあえず App Configuration を使わないケース

Azure Functions のプロジェクトを作って以下の NuGet パッケージを入れます。DIしたいので。

  • Microsoft.Azure.Functions.Extensions

local.settings.json を以下のようにして…

{"IsEncrypted": false,
    "Values": {"AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "Sample:Message": "Hello from local.settings.json"
    }}

そして、Startup.cs で SampleObject というクラスに Sample:Message が設定されるようにします。

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(AppConfigFunc.Startup))]

namespace AppConfigFunc
{
    publicclass Startup : FunctionsStartup
    {
        private IConfiguration Configuration { get; }

        public Startup()
        {
            var config = new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddJsonFile("local.settings.json", true);

            // 後で App Configuration から取り込む予定

            Configuration = config.Build();       
        }

        publicoverridevoid Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.Configure<SampleObject>(Configuration.GetSection("Sample"));
        }
    }

    publicclass SampleObject
    {
        publicstring Message { get; set; }
    }
}

適当に関数で使ってみましょう。SampleObject を DI して Message を返すだけの関数を作ります。

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.Extensions.Options;

namespace AppConfigFunc
{
    publicclass SayHello
    {
        privatereadonly SampleObject _sampleObject;
        public SayHello(IOptions<SampleObject> sampleObject)
        {
            _sampleObject = sampleObject.Value;
        }

        [FunctionName("SayHello")]
        public IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            returnnew OkObjectResult(_sampleObject);
        }
    }
}

実行して SayHello 関数を呼び出すと…

f:id:okazuki:20200303215506p:plain

思った通りですね。

App Configuration 対応

では、App Configuration 対応してみます。以下の NuGet パッケージを追加します。

  • Microsoft.Extensions.Configuration.AzureAppConfiguration

Startup.cs を以下のようにして本番のときだけ App Configuration から値を取るようにしてみました。 今回はローカルでは local.settings.json を使う想定で

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(AppConfigFunc.Startup))]

namespace AppConfigFunc
{
    publicclass Startup : FunctionsStartup
    {
        public IConfiguration Configuration { get; }

        public Startup()
        {
            var config = new ConfigurationBuilder()
                .AddEnvironmentVariables()
                .AddJsonFile("local.settings.json", true);

            // App Configuration から取り込む
            var builtConfig = config.Build();
            if (builtConfig["AZURE_FUNCTIONS_ENVIRONMENT"] != "Development")
            {
                config.AddAzureAppConfiguration(builtConfig["AppConfigurationConnectionString"]);
            }

            Configuration = config.Build();       
        }

        publicoverridevoid Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.Configure<SampleObject>(Configuration.GetSection("Sample"));
        }
    }

    publicclass SampleObject
    {
        publicstring Message { get; set; }
    }
}

コードは安定のしばやんの blog を参考にしました。

blog.shibayan.jp

そして、App Configuration に以下のような値を設定します。

f:id:okazuki:20200303222007p:plain

ARM Template で作った Function Apps にデプロイして実行すると、以下のような値になりました!やったね!

f:id:okazuki:20200303222042p:plain

App Configuration の設定を動的に変更したい

その時用のメモとしてドキュメントへのリンクをぺたり。

docs.microsoft.com

ソースコード

github.com


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>