概要
クイック スタート:Visual Studio Code を使用して Azure で関数を作成するの内容を参考に、AzureFunctionsを触ってみます。
環境情報
2020/6/3時点
- MacOS 10.15.5
- Node.js v12.18.0 (最新は14.4.0でしたがLTSがおすすめらしいのでLTSのバージョンにしました。)
- Visual Studio Code 1.45.1
- Azure Functions Plugin 0.22.1
事前準備
-
Microsoft Azureアカウント(無料)を作成しておく
- アカウント作成時にGitHubアカウントでログインもしくは新規でメールアドレスを登録してアカウントを作成
- 電話番号、クレジットカード情報の登録も必要
- クレジットカード情報は、認証に利用し、アップグレードを叫ばない限り費用が発生することはないようです。
- Visual Studio Codeを使うのでインストールしておく
- 拡張機能としてAzure Functionsを使うのでインストールしておく
- Node.jsをインストールしておく
- MacにNode.jsをインストールが参考になります。
ローカルプロジェクトを作成する
ローカルプロジェクトを作成するの内容をトレースしていきます。
上記記事と、最新の環境とで差があるようですが、概ね手順の通り進められます。
新しいプロジェクトの作成
プロジェクトワークスペースのディレクトリを指定
これらの手順は、ワークスペースの外部で実行するように設計されています。 ここでは、ワークスペースに含まれるプロジェクト フォルダーは選択しないでください。
という注意書きがあるので、どういうことなのかやってみました。
もともと別のソースを管理するワークスペース「SRC」のワークスペースをそのまま選択して進めてみたところ、
既存のワークスペースに「HttpExample」というディレクトリだけでなく、そのディレクトリの外側に.gitignore
やhost.json
などいろいろなファイルが生成されてしまいました。
なので、既存のワークスペースがごちゃごちゃするから、新しいフォルダを指定してくださいね。
という注意書きのようですね。
新規フォルダを作成してそこを指定すると、きれいに関連するファイルだけがまとまって作成されました。
プロンプトで次の情報を入力する
Select a language
でJavaScript
を選択する。
Select a template for your project's first function
でHTTP trigger
を選択する。
Provide a function name
で任意のプロジェクト名を入力します。
ここでは、クイックスタートのサイトで指定されているHttpExample
という名前を指定していきます。
Authorization level
でAnonymous
を指定する。
Anonymousに設定することで、APIキーが不要な単純なHTTPリクエストによるAzure Functionを体験できるようです。
これだとPublicに公開された誰でも実行できるものになってしまうということであれば、別の承認レベルを指定する必要がありそうですね。
関数をローカルで実行する
なんと、ここでAzure Functions Core Toolsというツールを使って、関数のテストを行うようです。
事前準備で、VSCodeやらNode.jsをセットアップさせておきながら、まだ必要な環境があるとは。。。
Azure Functions Core Toolsのセットアップ
Macの環境なので、Terminalを起動してbrew tap azure/functions
を実行。
$ brew tap azure/functions
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
bombadillo coredns
==> Updated Formulae
abcmidi aws-cdk awscli@1 composer dnscontrol elektra flow ghq imagemagick liblouis node@10 rbspy simple-scan
aliyun-cli awscli buildifier csvq doctl eureka geoserver grin-wallet ktlint node node@12 semgrep
==> Deleted Formulae
baidupcs-go
==> Tapping azure/functions
Cloning into '/usr/local/Homebrew/Library/Taps/azure/homebrew-functions'...
remote: Enumerating objects: 71, done.
remote: Counting objects: 100% (71/71), done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 338 (delta 48), reused 41 (delta 29), pack-reused 267
Receiving objects: 100% (338/338), 50.35 KiB | 305.00 KiB/s, done.
Resolving deltas: 100% (184/184), done.
Tapped 4 formulae (31 files, 93.6KB).
続いてbrew install azure-functions-core-tools@3
を実行。
$ brew install azure-functions-core-tools@3
==> Installing azure-functions-core-tools@3 from azure/functions
==> Downloading https://functionscdn.azureedge.net/public/3.0.2534/Azure.Functions.Cli.osx-x64.3.0.2534.zip
######################################################################## 100.0%
Telemetry
---------
The Azure Functions Core tools collect usage data in order to help us improve your experience.
The data is anonymous and doesn't include any user specific or personal information. The data is collected by Microsoft.
You can opt-out of telemetry by setting the FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.
🍺 /usr/local/Cellar/azure-functions-core-tools@3/3.0.2534: 5,114 files, 564.9MB, built in 21 seconds
VSCodeでF5キーを押下
F5キーを押下すると、こんな感じになります。
Azure Functions Core Tools
をインストールしたからこんな感じになるのか、インストールしなくても実は動くのか。。。インストールする前に試せばよかったです。
とりあえずTERMINAL
に出力された結果としては以下のような感じでした。
> Executing task: npm install <
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN azurefunctions@1.0.0 No description
npm WARN azurefunctions@1.0.0 No repository field.
npm WARN azurefunctions@1.0.0 No license field.
up to date in 0.653s
found 0 vulnerabilities
Terminal will be reused by tasks, press any key to close it.
> Executing task: func host start <
%%%%%%
%%%%%%
@ %%%%%% @
@@ %%%%%% @@
@@@ %%%%%%%%%%% @@@
@@ %%%%%%%%%% @@
@@ %%%% @@
@@ %%% @@
@@ %% @@
%%
%
Azure Functions Core Tools (3.0.2534 Commit hash: bc1e9efa8fa78dd1a138dd1ac1ebef97aac8d78e)
Function Runtime Version: 3.0.13353.0
[2020/06/03 11:08:07] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:python
[2020/06/03 11:08:07] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:java
[2020/06/03 11:08:07] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:powershell
[2020/06/03 11:08:07] Building host: startup suppressed: 'False', configuration suppressed: 'False', startup operation id: 'd6b60201-83fa-46d6-8a79-67bd2d429035'
[2020/06/03 11:08:08] Reading host configuration file '/Users/you_name_is_yu/Develop/AzureFunctions/host.json'
[2020/06/03 11:08:08] Host configuration file read:
[2020/06/03 11:08:08] {
[2020/06/03 11:08:08] "version": "2.0",
[2020/06/03 11:08:08] "extensionBundle": {
[2020/06/03 11:08:08] "id": "Microsoft.Azure.Functions.ExtensionBundle",
[2020/06/03 11:08:08] "version": "[1.*, 2.0.0)"
[2020/06/03 11:08:08] }
[2020/06/03 11:08:08] }
[2020/06/03 11:08:08] Reading functions metadata
[2020/06/03 11:08:08] 1 functions found
[2020/06/03 11:08:08] Looking for extension bundle Microsoft.Azure.Functions.ExtensionBundle at /var/folders/pf/mbns7g5n6nlfj48466cy3kj40000gn/T/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle
[2020/06/03 11:08:08] Fetching information on versions of extension bundle Microsoft.Azure.Functions.ExtensionBundle available on https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index.json
[2020/06/03 11:08:09] Downloading extension bundle from https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/1.1.1/Microsoft.Azure.Functions.ExtensionBundle.1.1.1.zip to /var/folders/pf/mbns7g5n6nlfj48466cy3kj40000gn/T/62e2229d-4a18-4dca-92f3-7f12aef4f16e/Microsoft.Azure.Functions.ExtensionBundle.1.1.1.zip
[2020/06/03 11:08:13] Completed downloading extension bundle from https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/1.1.1/Microsoft.Azure.Functions.ExtensionBundle.1.1.1.zip to /var/folders/pf/mbns7g5n6nlfj48466cy3kj40000gn/T/62e2229d-4a18-4dca-92f3-7f12aef4f16e/Microsoft.Azure.Functions.ExtensionBundle.1.1.1.zip
[2020/06/03 11:08:13] Extracting extension bundle at /var/folders/pf/mbns7g5n6nlfj48466cy3kj40000gn/T/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/1.1.1
[2020/06/03 11:08:13] Zip extraction complete
[2020/06/03 11:08:13] Loading Extention bundle from /var/folders/pf/mbns7g5n6nlfj48466cy3kj40000gn/T/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/1.1.1
[2020/06/03 11:08:13] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:python
[2020/06/03 11:08:13] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:java
[2020/06/03 11:08:13] FUNCTIONS_WORKER_RUNTIME set to node. Skipping WorkerConfig for language:powershell
[2020/06/03 11:08:13] Initializing Warmup Extension.
[2020/06/03 11:08:14] Initializing Host. OperationId: 'd6b60201-83fa-46d6-8a79-67bd2d429035'.
[2020/06/03 11:08:14] Host initialization: ConsecutiveErrors=0, StartupCount=1, OperationId=d6b60201-83fa-46d6-8a79-67bd2d429035
[2020/06/03 11:08:14] LoggerFilterOptions
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "MinLevel": "None",
[2020/06/03 11:08:14] "Rules": [
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "ProviderName": null,
[2020/06/03 11:08:14] "CategoryName": null,
[2020/06/03 11:08:14] "LogLevel": null,
[2020/06/03 11:08:14] "Filter": "<AddFilter>b__0"
[2020/06/03 11:08:14] },
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2020/06/03 11:08:14] "CategoryName": null,
[2020/06/03 11:08:14] "LogLevel": "None",
[2020/06/03 11:08:14] "Filter": null
[2020/06/03 11:08:14] },
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2020/06/03 11:08:14] "CategoryName": null,
[2020/06/03 11:08:14] "LogLevel": null,
[2020/06/03 11:08:14] "Filter": "<AddFilter>b__0"
[2020/06/03 11:08:14] }
[2020/06/03 11:08:14] ]
[2020/06/03 11:08:14] }
[2020/06/03 11:08:14] FunctionResultAggregatorOptions
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "BatchSize": 1000,
[2020/06/03 11:08:14] "FlushTimeout": "00:00:30",
[2020/06/03 11:08:14] "IsEnabled": true
[2020/06/03 11:08:14] }
[2020/06/03 11:08:14] SingletonOptions
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "LockPeriod": "00:00:15",
[2020/06/03 11:08:14] "ListenerLockPeriod": "00:00:15",
[2020/06/03 11:08:14] "LockAcquisitionTimeout": "10675199.02:48:05.4775807",
[2020/06/03 11:08:14] "LockAcquisitionPollingInterval": "00:00:05",
[2020/06/03 11:08:14] "ListenerLockRecoveryPollingInterval": "00:01:00"
[2020/06/03 11:08:14] }
[2020/06/03 11:08:14] HttpOptions
[2020/06/03 11:08:14] {
[2020/06/03 11:08:14] "DynamicThrottlesEnabled": false,
[2020/06/03 11:08:14] "MaxConcurrentRequests": -1,
[2020/06/03 11:08:14] "MaxOutstandingRequests": -1,
[2020/06/03 11:08:14] "RoutePrefix": "api"
[2020/06/03 11:08:14] }
[2020/06/03 11:08:14] Starting JobHost
[2020/06/03 11:08:14] Starting Host (HostId=younameisyupc-237003343, InstanceId=309bf51b-da3c-4db1-be93-1afdc15b677e, Version=3.0.13353.0, ProcessId=5908, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
[2020/06/03 11:08:14] Loading functions metadata
[2020/06/03 11:08:14] 1 functions loaded
[2020/06/03 11:08:14] Loading proxies metadata
[2020/06/03 11:08:14] Initializing Azure Function proxies
[2020/06/03 11:08:16] 0 proxies loaded
[2020/06/03 11:08:16] Starting worker process:node --inspect=9229 "/usr/local/Cellar/azure-functions-core-tools@3/3.0.2534/workers/node/dist/src/nodejsWorker.js" --host 127.0.0.1 --port 50181 --workerId c50406b7-d0c6-48fa-a29d-c66ec65f8d4f --requestId 83f76573-42dc-499a-80b9-a44874849ea9 --grpcMaxMessageLength 134217728
[2020/06/03 11:08:17] node process with Id=5919 started
[2020/06/03 11:08:17] Generating 1 job function(s)
[2020/06/03 11:08:17] Found the following functions:
[2020/06/03 11:08:17] Host.Functions.HttpExample
[2020/06/03 11:08:17]
[2020/06/03 11:08:17] Initializing function HTTP routes
[2020/06/03 11:08:17] Mapped function route 'api/HttpExample' [get,post] to 'HttpExample'
[2020/06/03 11:08:17]
[2020/06/03 11:08:17] Host initialized (2741ms)
[2020/06/03 11:08:17] Host started (2750ms)
[2020/06/03 11:08:17] Job host started
[2020/06/03 11:08:17] Debugger listening on ws://127.0.0.1:9229/d7c34f05-e633-4dec-88f4-140ed939a894
[2020/06/03 11:08:17] For help, see: https://nodejs.org/en/docs/inspector
Hosting environment: Production
Content root path: /Users/you_name_is_yu/Develop/AzureFunctions
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.
Http Functions:
HttpExample: [GET,POST] http://localhost:7071/api/HttpExample
[2020/06/03 11:08:17] Worker c50406b7-d0c6-48fa-a29d-c66ec65f8d4f connecting on 127.0.0.1:50181
[2020/06/03 11:08:22] Host lock lease acquired by instance ID '000000000000000000000000354A045E'.
[2020/06/03 11:08:23] Debugger attached.
気になるポイントとしてはこんな感じで、HttpFunctionが動き始めたようなメッセージが出力されている部分でしょうか。
http://localhost:7071/api/HttpExample
ただ、このURLのままアクセスしてもダメみたいで、以下のように、クエリパラメータとしてname=Functions
を指定する必要があるようです。
http://localhost:7071/api/HttpExample?name=Functions
アクセスしてみると、よくあるHello World
のような感じで、Hello Functions
という文字が出力されました。
ブラウザにアクセスした時点でTERMINALに出力される内容としては以下のような内容が出力されています。
[2020/06/03 11:13:27] Executing HTTP request: {
[2020/06/03 11:13:27] "requestId": "816dc4fe-2914-4e86-99a5-7820ab231808",
[2020/06/03 11:13:27] "method": "GET",
[2020/06/03 11:13:27] "uri": "/api/HttpExample"
[2020/06/03 11:13:27] }
[2020/06/03 11:13:27] Executing 'Functions.HttpExample' (Reason='This function was programmatically called via the host APIs.', Id=32b32a60-2b58-4988-8fd5-329484b2a50d)
[2020/06/03 11:13:28] JavaScript HTTP trigger function processed a request.
[2020/06/03 11:13:28] Executed 'Functions.HttpExample' (Succeeded, Id=32b32a60-2b58-4988-8fd5-329484b2a50d)
[2020/06/03 11:13:28] Executed HTTP request: {
[2020/06/03 11:13:28] "requestId": "816dc4fe-2914-4e86-99a5-7820ab231808",
[2020/06/03 11:13:28] "method": "GET",
[2020/06/03 11:13:28] "uri": "/api/HttpExample",
[2020/06/03 11:13:28] "identities": [
[2020/06/03 11:13:28] {
[2020/06/03 11:13:28] "type": "WebJobsAuthLevel",
[2020/06/03 11:13:28] "level": "Admin"
[2020/06/03 11:13:28] }
[2020/06/03 11:13:28] ],
[2020/06/03 11:13:28] "status": 200,
[2020/06/03 11:13:28] "duration": 1095
[2020/06/03 11:13:28] }
[2020/06/03 11:13:28] Executing HTTP request: {
[2020/06/03 11:13:28] "requestId": "ec5ffac0-d06e-4795-ae24-e2bb5b2f9cd7",
[2020/06/03 11:13:28] "method": "GET",
[2020/06/03 11:13:28] "uri": "/favicon.ico"
[2020/06/03 11:13:28] }
[2020/06/03 11:13:28] Executed HTTP request: {
[2020/06/03 11:13:28] "requestId": "ec5ffac0-d06e-4795-ae24-e2bb5b2f9cd7",
[2020/06/03 11:13:28] "method": "GET",
[2020/06/03 11:13:28] "uri": "/favicon.ico",
[2020/06/03 11:13:28] "identities": [],
[2020/06/03 11:13:28] "status": 404,
[2020/06/03 11:13:28] "duration": 352
[2020/06/03 11:13:28] }
デバッガーを終了
Disconnectボタンを押下するか、Ctrl+Cを押下することでデバッグを終了します。
Azureへのサインイン
Azure Functionsのアプリを発行するには、Azureへのサインインが必要です。
ブラウザでのログインが求められたので、私の場合はGitHubアカウントでサインインします。
サインインしてしまえば、表示されたブラウザは閉じてOKです。
Azure にプロジェクトを発行する
Create new Function App in Azure
を選択する。
※Advancedは選択しないでとのこと。
今回はNode.jsのバージョンを12.18.0としているため、Node.js 12を選択します。
Japan East
を選択します。
パフォーマンスを向上させるために、お近くのリージョンを選択してください
完了すると以下のようになります。
View output
ボタンを押下することで、作成とデプロイの結果を確認することができます。
8:30:46 PM: Creating resource group "yuyamaguchifunctionshttp" in location "japaneast"...
8:30:46 PM: Successfully created resource group "yuyamaguchifunctionshttp".
8:30:46 PM: Creating storage account "yuyamaguchifunctionshttp" in location "japaneast" with sku "Standard_LRS"...
8:31:18 PM: Successfully created storage account "yuyamaguchifunctionshttp".
8:31:18 PM: Verifying that Application Insights is available for this location...
8:31:18 PM: Creating Application Insights resource "yuyamaguchifunctionshttp"...
8:31:21 PM: Successfully created Application Insights resource "yuyamaguchifunctionshttp".
8:31:21 PM: Creating new function app "Yu-Yamaguchi-Functions-HttpExample"...
8:32:09 PM: Successfully created function app "Yu-Yamaguchi-Functions-HttpExample": https://yu-yamaguchi-functions-httpexample.azurewebsites.net
8:32:13 PM Yu-Yamaguchi-Functions-HttpExample: Creating zip package...
8:32:13 PM Yu-Yamaguchi-Functions-HttpExample: Starting deployment...
8:32:22 PM Yu-Yamaguchi-Functions-HttpExample: Updating submodules.
8:32:22 PM Yu-Yamaguchi-Functions-HttpExample: Preparing deployment for commit id 'a320bfa83a'.
8:32:23 PM Yu-Yamaguchi-Functions-HttpExample: Skipping build. Project type: Run-From-Zip
8:32:23 PM Yu-Yamaguchi-Functions-HttpExample: Skipping post build. Project type: Run-From-Zip
8:32:23 PM Yu-Yamaguchi-Functions-HttpExample: Triggering recycle (preview mode disabled).
8:32:27 PM Yu-Yamaguchi-Functions-HttpExample: Syncing 2 function triggers with payload size 158 bytes successful.
8:32:28 PM Yu-Yamaguchi-Functions-HttpExample: Deployment successful.
8:32:42 PM Yu-Yamaguchi-Functions-HttpExample: Started postDeployTask "npm install".
8:32:43 PM Yu-Yamaguchi-Functions-HttpExample: Querying triggers...
8:32:48 PM Yu-Yamaguchi-Functions-HttpExample: HTTP Trigger Urls:
HttpExample: https://yu-yamaguchi-functions-httpexample.azurewebsites.net/api/HttpExample
Azure で関数を実行する
コピーしたURLは以下の通りです。
https://yu-yamaguchi-functions-httpexample.azurewebsites.net/api/HttpExample
これにローカル環境での動作確認でも指定したクエリ文字列?name=Functions
を指定したURLを生成し、ブラウザでアクセスします。
https://yu-yamaguchi-functions-httpexample.azurewebsites.net/api/HttpExample?name=Functions
このURLをみる限り、ユニークなFunctionの名前とは、グローバルでのユニークとなるように指定する必要があるようですね。
無闇に作らず、命名には注意が必要そうです。
Azureのポータルサイトにアクセスすると、デプロイしたFunctionが確認できます。
Azure Functionsはリクエスト数が多いとその分費用?がかかるような従量課金だと思いますので、ここで作ったFunctionは消しておきますw
なので、ここに載せているFunctionのURLにアクセスしても意味が無いので悪しからずm(_ _)m
以上で、クイックスタートの内容は完了です。
まだ何ができるかわかっていませんが、できればOffice365とか会社で使っているので、TeamsとかOneDriveのドキュメントとか、その辺りといい感じのことができると嬉しいなと思っています。