Azure Function + Go でハマった話


タイトル通りの備忘録です。チュートリアルは以下に存在していますがちょっとだけハマったのでメモ代わりに残しておきます。

[Visual Studio Code を使用して Go または Rust の関数を作成する - Azure Functions | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/azure-functions/create-first-function-vs-code-other?tabs=go%2Clinux)

## functions の作成

VSCode からでも、`func`コマンドでも可能なのでサクットつくります。

`func` コマンドなら以下のような感じです。

```sh
func init --worker-runtime custom  --template HttpTrigger --name HelloFunction --authlevel anonymous
func new --language custom --template HttpTrigger --name HelloFunction --authlevel anonymous
```

## host.json

HTTP トリガーのみで構成されるFunctionsの場合、カスタムハンドラー独自のペイロードではなく、Httpのペイロードそのものを受け取れますので、以下設定を忘れないようにしましょう。

- `enableForwardingHttpRequest` 

あとは、`defaultExecutablePath` に実行ファイルの指定を忘れないように。

```host.json
"customHandler": {
  "description": {
    "defaultExecutablePath": "handler", // 実行ファイル
    "workingDirectory": "",
    "arguments": []
  },
  "enableForwardingHttpRequest": true // バイパス設定
}
```

## デプロイ向けバイナリの作成

ここでハマったのですが、Learnには以下のように書いてありますが、これでビルドすると dyamic link になって、Azure上では動きませんでした（私の環境では）

```sh
$ GOOS=linux GOARCH=amd64 go build handler.go
$ ldd handler
        linux-vdso.so.1 (0x00007fff7edd0000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f649bf59000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f649c171000)
```

これに気づくまでしばらく、Windowsで実行したり、Portalで診断したりと色々ためして時間を潰してしまいましたが、気づいてしまえばくだらない話です。

static link するには色々方法があるようですが、`CGO_ENABLED=0` を付けてコンパイルして回避しました。

```sh
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build handler.go
$ ldd handler
        not a dynamic executable
```

## 余談

Portalには「問題の解決と診断」ってのがあって、失敗の原因をさくっと見つけてくれるものがあります。当初は、そここ以下のような致命的なエラーが表示されていて、これに拘りすぎて時間を潰した感があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/1d75b81c-ec1e-bfd4-a462-8e76d62fb8cd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/065d9683-78b3-b151-9eb3-fdc56c9b71fb.png)

そこに表示されているリンクを辿って、
- https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings#valid-linuxfxversion-values

有効なLinuxバージョンを辿ります。カスタムハンドラの場合は空のままでOKそうですが、この診断ではエラーになってしまうようです。バグな気がしますが。

```
$ az functionapp list-runtimes --os linux --query "[].{stack:join(' ', [runtime, version]), LinuxFxVersion:linux_fx_version, SupportedFunctionsVersions:to_string(supported_functions_versions[])}" --output table
Stack              LinuxFxVersion       SupportedFunctionsVersions
-----------------  -------------------  ----------------------------
dotnet-isolated 8  DOTNET-ISOLATED|8.0  ["4"]
dotnet-isolated 7  DOTNET-ISOLATED|7.0  ["4"]
dotnet-isolated 6  DOTNET-ISOLATED|6.0  ["4"]
dotnet 6           DOTNET|6.0           ["4"]
node 20            Node|20              ["4"]
node 18            Node|18              ["4"]
node 16            Node|16              ["4"]
node 14            Node|14              ["4","3"]
python 3.11        Python|3.11          ["4"]
python 3.10        Python|3.10          ["4"]
python 3.9         Python|3.9           ["4","3"]
python 3.8         Python|3.8           ["4","3"]
python 3.7         Python|3.7           ["4","3"]
java 21.0          Java|21              ["4"]
java 17.0          Java|17              ["4"]
java 11.0          Java|11              ["4","3"]
java 8.0           Java|8               ["4","3"]
powershell 7.2     PowerShell|7.2       ["4"]
custom                                  ["4","3"]

## 結論

ちょっとしたAPIを用意したいだけだったので、Goに拘らなくてもよかったw。