12/02 Azure Functions with Core Tools

2020/12/03に公開

この記事は、Serverless Hello World Advent Calendar 2020の2日目です。

Azure Functions Core Toolsの導入

Azure Functions Core Tools のインストールにしたがって導入します。

関数アプリの作成

Azure Functionsでは、複数の関数を束ねた「関数アプリ」という単位で構成します。
Node.jsで関数アプリのプロジェクトを作成します。

% func init adventcalendar02
Select a number for worker runtime:
1. dotnet
2. node
3. python
4. powershell
Choose option: 2
node
Select a number for language:
1. javascript
2. typescript
Choose option: 1
javascript
Writing package.json
Writing .gitignore
Writing host.json
Writing local.settings.json
Writing /home/masa/work/serverless-helloworld/02/adventcalendar02/.vscode/extensions.json

関数の作成

続いて、関数アプリの中にHTTPで呼び出せる関数を作成します。

% cd adventcalendar02
% func new
Select a number for template:
1. Azure Blob Storage trigger
2. Azure Cosmos DB trigger
3. Durable Functions activity
4. Durable Functions HTTP starter
5. Durable Functions orchestrator
6. Azure Event Grid trigger
7. Azure Event Hub trigger
8. HTTP trigger
9. IoT Hub (Event Hub)
10. Azure Queue Storage trigger
11. SendGrid
12. Azure Service Bus Queue trigger
13. Azure Service Bus Topic trigger
14. SignalR negotiate HTTP trigger
15. Timer trigger
Choose option: 8
HTTP trigger
Function name: [HttpTrigger] hello
Writing /home/masa/work/serverless-helloworld/02/adventcalendar02/hello/index.js
Writing /home/masa/work/serverless-helloworld/02/adventcalendar02/hello/function.json
The function "hello" was created successfully from the "HTTP trigger" template.

生成されたファイルの確認

host.jsonには関数アプリ共通の設定が書かれます。

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[1.*, 2.0.0)"
  }
}

local.settings.jsonには、関数アプリをローカル環境で動かすときに必要な設定が書かれます。このファイルは.gitignoreでソースコード管理から除外されます。

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": ""
  }
}

hello/function.jsonには、関数ごとの設定が書かれます。

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

hello/index.jsが、関数の本体です。

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    const name = (req.query.name || (req.body && req.body.name));
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };
}

認証を不要に設定

生成されたテンプレートそのままだと、Azureにデプロイすると関数毎に設定されたキーが必要となります。認証が不要となるようにhello/function.jsonを修正し、authLevelanonymousにします。

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",

      ...(省略)...
    }
  ]
}

ローカル環境での動作確認

ローカル環境で関数アプリを動かしてみます。

% func start

Azure Functions Core Tools
Core Tools Version:       3.0.2996 Commit hash: c54cdc36323e9543ba11fb61dd107616e9022bba
Function Runtime Version: 3.0.14916.0


Functions:

        hello: [GET,POST] http://localhost:7071/api/hello

For detailed output, run func with --verbose flag.
[2020-12-02T20:07:47.114Z] Worker process started and initialized.

別のターミナルを開いて、表示されたエンドポイントをcURLで叩いてみます。

% curl -v http://localhost:7071/api/hello
*   Trying 127.0.0.1:7071...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 7071 (#0)
> GET /api/hello HTTP/1.1
> Host: localhost:7071
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 02 Dec 2020 20:08:24 GMT
< Content-Type: text/plain; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.%                                            

nameを渡せ、とのことなので渡してみます。

% curl -v 'http://localhost:7071/api/hello?name=world'
*   Trying 127.0.0.1:7071...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 7071 (#0)
> GET /api/hello?name=world HTTP/1.1
> Host: localhost:7071
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Wed, 02 Dec 2020 20:09:18 GMT
< Content-Type: text/plain; charset=utf-8
< Server: Kestrel
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
Hello, world. This HTTP triggered function executed successfully.%                                                      

func startを実行しているターミナルには、ログが表示されます。

[2020-12-02T20:09:19.060Z] Executing 'Functions.hello' (Reason='This function was programmatically called via the host APIs.', Id=6dda99c1-abb6-4b6d-9bf4-d4d8f8526fb2)
[2020-12-02T20:09:19.065Z] JavaScript HTTP trigger function processed a request.
[2020-12-02T20:09:19.066Z] Executed 'Functions.hello' (Succeeded, Id=6dda99c1-abb6-4b6d-9bf4-d4d8f8526fb2, Duration=22ms)

Azure上で関数アプリを作成

関数用の関連 Azure リソースを作成するにしたがって、Azure上に関数アプリとそれに必要なリソースを作成します。

関数アプリを作成するためには、それを収容するリソースグループと、ストレージアカウントが必要です。

% az group create --name adventcalendar02 --location japaneast
% az storage account create --name nekoruriadventcalendar02 --resource-group adventcalendar02 --sku Standard_LRS --location japaneast

準備ができたので、関数アプリを作成します。

% az functionapp create --resource-group adventcalendar02 --consumption-plan-location japaneast --runtime node --runtime-version 12 --functions-version 3 --name adventcalendar02 --storage-account nekoruriadventcalendar02

Application Insights "adventcalendar02" was created for this Function App. You can visit https://portal.azure.com/#resource/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/adventcalendar02/providers/microsoft.insights/components/adventcalendar02/overview to view your Application Insights component
{
  ...(省略)...
}

監視に使われるApplication Insightsリソースも作成されたことが表示されます。

デプロイ

func azure functionapp publishでデプロイしてくれます。

% func azure functionapp publish adventcalendar02
Getting site publishing info...
Creating archive for current directory...
Uploading 1.28 KB [#####################################################################]
Upload completed successfully.
Deployment completed successfully.
Syncing triggers...
Functions in adventcalendar02:
    hello - [httpTrigger]
        Invoke url: https://adventcalendar02.azurewebsites.net/api/hello

Azure上にデプロイされたエンドポイントが表示されるので、cURLで叩いてみます。

% curl -v 'https://adventcalendar02.azurewebsites.net/api/hello?name=world'

...(省略)...

> GET /api/hello?name=world HTTP/2
> Host: adventcalendar02.azurewebsites.net
> user-agent: curl/7.68.0
> accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200 
< content-length: 65
< content-type: text/plain; charset=utf-8
< request-context: appId=cid-v1:7d7dd11b-17e7-4502-9b3f-b979f4634290
< date: Wed, 02 Dec 2020 20:22:34 GMT
< 
* Connection #0 to host adventcalendar02.azurewebsites.net left intact
Hello, world. This HTTP triggered function executed successfully.%                                                      

Azure上にhello関数をデプロイできました。

Discussion