【備忘】Api Gatewayのステージ変数とLambdaのエイリアスが繋がることを理解する

# まえがき
Api GatewayとLambdaで構成されているサーバーレス環境の話。
Api Gatewayの複数のエンドポイントと同じLambda関数を紐付けることができます。
たとえばdev環境とprod環境があってLambda関数がひとつである場合、dev環境への変更がprod環境へも反映されることになります。
dev環境で行った変更をテストした上でprod環境へ反映させたい場合、Api Gatewayのステージ変数とLambdaのエイリアスが役に立ちます。
ネット上にやり方は書いてありましたが、図解が見つけられなかったため、ここに備忘として残したいと思います。
細かい設定値や設定方法はネット上に多く存在したため省きます。

# 図解
いきなり結論ですが、Api Gatewayのステージ変数とLambda関数のエイリアスのつながりは以下のようになります。
Lambda側ではエイリアス名を設定し、Api Gateway側ではステージ変数を設定することで、連携できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/80625496-79d5-ebc9-e3b4-a1b1a3ff0ad7.png)

# ここでの設定値
## Lambda
### 変更前（v1）のコード
```python
import base64

def lambda_handler(event, context):
    str_html = '''
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>Version Test</title>
        <meta charset="utf-8"/>
    </head>
    <body>
        <h1>Version 1</h1>
    </body>
</html>'''
    bytes_html = bytes(str_html, 'utf-8')
    result = base64.b64encode(bytes_html)
    
    return result
```
### 新しいバージョンの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/21ae06e5-5a18-24e4-eece-36848d03b980.png)

### 変更後（$latest）のコード
`Version 1`を`Version 2`に変えただけです。
```python
import base64

def lambda_handler(event, context):
    str_html = '''
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>Version Test</title>
        <meta charset="utf-8"/>
    </head>
    <body>
        <h1>Version 2</h1>
    </body>
</html>'''
    bytes_html = bytes(str_html, 'utf-8')
    result = base64.b64encode(bytes_html)
    
    return result
```
### エイリアスの作成
`$latest`バージョンに紐づく`dev`エイリアスと、`v1`バージョンに紐づく`prod`エイリアスを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/fddc3ae2-41c0-4a58-8e8c-da72709140ec.png)


## Api Gateway
### Api Gatewayの作成
Api Gatewayの作成は省きます。前回の記事で作成したものと同一なので、リンクを貼っておきます。
[Pythonコードの中に記載されたHTMLテキストをブラウザで表示する(Api Gateway,Lambda)](https://qiita.com/jianyi/items/034da485eea6c17d697a)

### Lambda関数をステージ変数を加えて指定
ここでのLambda関数名は「versionTestFunc」です。
ステージ変数を使用してLambda関数をバージョン指定で呼び出すには、`[Lambda関数名]:${stageVariables.[ステージ変数]}`という形で指定します。
※ここでは`versionTestFunc:${stageVariables.alias}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/34128f88-8b4d-13a1-3613-eb431e8918d4.png)

### 権限の付与
上でチェックマークをクリックすると、下記の画面が表示されます。権限を付与する必要があるため、コマンドが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/8d7a8a55-3f97-b161-710a-e429a9567c86.png)
表示されているコマンドにおいて、`[Lambda関数名]:${stageVariables.[ステージ変数]}`の`[ステージ変数]`の部分のみ、自分の環境に置き換えてaws cliで実行します。
今回は`dev`と`prod`のふたつのステージ変数を使用しているため、２回コマンドを実行しました。
```shell
% aws lambda add-permission   --function-name "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:versionTestFunc:dev"   --source-arn "arn:aws:execute-api:us-east-1:XXXXXXXXXXXX:xxxxxxxxxx/*/GET/"   --principal apigateway.amazonaws.com   --statement-id 868420a5-d63c-497c-a54d-1c68f0e2030d   --action lambda:InvokeFunction

{
    "Statement": "{\"Sid\":\"868420a5-d63c-497c-a54d-1c68f0e2030d\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:versionTestFunc:dev\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-1:XXXXXXXXXXXX:xxxxxxxxxx/*/GET/\"}}}"
}
% aws lambda add-permission   --function-name "arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:versionTestFunc:prod"   --source-arn "arn:aws:execute-api:us-east-1:XXXXXXXXXXXX:xxxxxxxxxx/*/GET/"   --principal apigateway.amazonaws.com   --statement-id 868420a5-d63c-497c-a54d-1c68f0e2030d   --action lambda:InvokeFunction
{
    "Statement": "{\"Sid\":\"868420a5-d63c-497c-a54d-1c68f0e2030d\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:XXXXXXXXXXXX:function:versionTestFunc:prod\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-1:XXXXXXXXXXXX:xxxxxxxxxx/*/GET/\"}}}"
}

```

### Apiのデプロイ
`dev`と`prod`という名前でデプロイしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/0b5d8769-d538-56c9-b78a-4ce7de4c2c16.png)
このままだとステージ変数を設定していないため、エンドポイントにアクセスすると下記のエラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/def72eb3-5752-2959-6855-026d1befdf9e.png)

### ステージ変数の設定
devステージには`alias`変数に`dev`という値を設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/7bb10c65-1bfd-4a0a-7643-52437a81cb82.png)

prodステージには`alias`変数に`prod`という値を設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/86ace607-f1dd-444a-700d-896e53988227.png)

# 動作確認
devのエンドポイントにアクセスすると、`$latest`のLambda関数に紐付いているため、Version 2が返されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/e1055d65-c64f-6fa3-9af1-74cbf194b65c.png)

prodのエンドポイントにアクセスすると、`v1`のLambda関数に紐付いているため、Version 1が返されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252459/11e8501e-ae7e-fbcd-aecc-8016265dd108.png)


# さいごに
ステージ変数を使用してLambda関数をバージョン指定で呼び出すには、Api Gatewayで`${stageVariables.[ステージ変数]}`という形で指定する必要があることが、ポイントだと思いました。

# 参考サイト
https://dev.classmethod.jp/articles/version-management-with-api-gateway-and-lambda/