AzureのFunctionsをCLIで使う（ローカルリソースの生成からデプロイまで）with Python

# 概要

公式のドキュメントにはリソースグループを作成するところからの説明があるのですが、既に存在するリソースグループの中にFunctionsをデプロイする方法については書かれていないようでしたので書きます。

公式ドキュメント: 
コマンド ラインから Python 関数を作成する - Azure Functions | Microsoft Learn
https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-cli-python?tabs=azure-cli%2Cbash&pivots=python-mode-configuration

なおPython関数を作成すると書いてありますが、基本的にデプロイまではシェルスクリプトを用いますので、あまり言語によって限定されるお話でもないと思いますが、やはりPythonを使っていただくのが参考コードをそのまま使えて良いと思います。

この記事のnode.jsを使ったJavascriptバージョンは以下よりご覧いただけます。

AzureのFunctionsをCLIで使う（ローカルリソースの生成からデプロイまで）with Javascript - Qiita - Qiita
https://qiita.com/fsd_yoshikawa/items/537334b9f1380dd8f76c



# 環境
Windows11, WSL2
```
❯ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
```

Azure CLI 
```
❯ az --version
azure-cli                         2.46.0 *

core                              2.46.0 *
telemetry                          1.0.8

Dependencies:
msal                              1.20.0
azure-mgmt-resource             21.1.0b1

```

Azure Functions Core Tools 
```
❯ func --version
4.0.5030
```

# 手順

:::note
前提として、まずはAzure上にリソースグループを持っていることが必要です。
:::

## ログイン
まずはCLIでAzureにログインします。

```
az login --use-device-code
```
上記のコマンドを実行すると、https\://microsoft.com/deviceloginというURLとcode(大文字英数字)のペアがターミナル上に表示されます。このcodeをコピーして表示されたURLに行って入力するとAzureにログインできます。

## Azure上にストレージの作成
Functionsを使うにはストレージが必要になりますので、まずはこれを作成します。
```
az storage account create --name <STORAGE_NAME> --resource-group <RESOURCE_GROUP_NAME>

```
:::note
<>の中の文字列はご自分の環境に合わせて入力してください。
:::


## Azure上にFunctions Appリソースの作成

```
az functionapp create --consumption-plan-location <LOCATION> --runtime python --runtime-version 3.8 --functions-version 4 --name <APP_NAME> --os-type linux --storage-account <STORAGE_NAME> --resource-group <RESOURCE_GROUP_NAME>
```


:::note
私の場合では上記\<LOCATION>はjapaneastを設定しました。
\<STORAGE_NAME>はストレージの作成の項目で作ったストレージの名前を入力します。
:::


# Functionsにデプロイするローカル環境の作成

```
func init AzureFunctions --python
```
上記のコマンドを実行すると、下記のようなファイル群が生成されます。

```
.
└── AzureFunctions
    ├── getting_started.md
    ├── host.json
    ├── local.settings.json
    └── requirements.txt
```

生成したディレクトリに移動します。
```
cd AzureFunctions
```

次に、Functions上で実行される実体ファイルをテンプレートを用いて作成します。
```
func new --name test --template "HTTP trigger"
```

するとtestディレクトリが新たに生成されて、下記のようなディレクトリ構造になります。

```
.
└── AzureFunctions
    ├── getting_started.md
    ├── host.json
    ├── local.settings.json
    ├── requirements.txt
    └── test
        ├── __init__.py
        └── function.json
```


このtestディレクトリ内の__init__.pyにFunctionsで動作するコードを書くことになります。
デフォルトでは以下のような状況になってます。

```python:__init__.py
import logging

import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )
```

これがどういう動作をするかテストするにはAzureFunctionsディレクトリで以下のコマンドを実行します。

```
func start
```

すると以下のような出力が得られます。

```
❯ func start
Found Python version 3.8.10 (python).

Azure Functions Core Tools
Core Tools Version:       4.0.5030 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.15.2.20177


Functions:

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

For detailed output, run func with --verbose flag.
[2023-04-06T08:08:49.781Z] Worker process started and initialized.
[2023-04-06T08:08:54.398Z] Host lock lease acquired by instance ID '000000000000000000000000017436A7'.
```

この http\://localhost:7071/api/test にアクセスすると、このコードをFunctions上にデプロイするとどういう振る舞いをするかのテストがローカルマシン上でできます。

試しにアクセスすると
```
This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.
```
とブラウザ上に表示されたかと思います。


# Azure上にデプロイ

最後に下記のコマンドを実行するとAzure上にFunctionsをデプロイできます。
```
func azure functionapp publish <APP_NAME>
```
:::note
\<APP_NAME>はFunctionsリソースの作成の項で設定した文字列を用います。
:::


以上です。