AWS CLIで Web サイトを構築、管理、運用する(23日目)

23 日目！
今日は、AWS Lambda 関数を作ってみます。
もちろん、AWS CLIで。

# 23日目の要約
サーバレスコンピューティング！

# AWS CLI の準備
このあたりをみて、好きなバージョンとお使いのOSにあった環境設定をしてくださいね。
なんなら、 AWS CloudShell で実行するのも楽でよいと思います。
この記事シリーズは、AWS CloudShell で実行し、実行例を載せています。

バージョン１
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv1.html

バージョン２
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html

# 概要
AWS Lambda 関数を作成します

# さあ、やってみよう！
## AWS Lambda 関数用の IAM ロールを作る
Lambda 関数がログを出力するために使う IAM ロールを作っていきます。
まずは ```iam create-policy``` コマンドでポリシーを作成します。

```sh
aws iam create-policy --policy-name pol-lambda-adventcalendar2021 \
--policy-document '{"Version": "2012-10-17","Statement":[{"Effect": "Allow", "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],"Resource": "*"}]}'
```

ポリシー作成が成功すると、以下のような json が返ります。

```json
{
    "Policy": {
        "PolicyName": "pol-lambda-adventcalendar2021",
        "PolicyId": "ANPA*****************",
        "Arn": "arn:aws:iam::************:policy/pol-lambda-adventcalendar2021",
        "Path": "/",
        "DefaultVersionId": "v1",
        "AttachmentCount": 0,
        "PermissionsBoundaryUsageCount": 0,
        "IsAttachable": true,
        "CreateDate": "2021-12-22T09:35:58+00:00",
        "UpdateDate": "2021-12-22T09:35:58+00:00"
    }
}
```

次に IAM ロールを作っていきます。
```iam create-role``` コマンドを実行します。

```sh
aws iam create-role --role-name role-lambda-AdventCalendar2021 \
--assume-role-policy-document '{"Version": "2012-10-17", "Statement":[{"Effect": "Allow", "Principal":{"Service":"lambda.amazonaws.com"}, "Action":"sts:AssumeRole"}]}'
```

IAM ロールの作成に成功すると以下のような json が返ります。

```json
{
    "Role": {
        "Path": "/",
        "RoleName": "role-lambda-AdventCalendar2021",
        "RoleId": "AROA*****************",
        "Arn": "arn:aws:iam::************:role/role-lambda-AdventCalendar2021",
        "CreateDate": "2021-12-22T09:36:43+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}
```

そして、IAM ロールに IAM ポリシーを関連づけます。

```sh
aws iam attach-role-policy --role-name role-lambda-AdventCalendar2021 \
--policy-arn arn:aws:iam::<AWSアカウントID>:policy/pol-lambda-adventcalendar2021
```

ロールへポリシーの割り当てが成功すると、特に何も返りません。

## Lambda 関数を作る

さて、今日の本番。Lambda 関数を作っていきます。
まずは、テキストエディタでコードを書いていきます。
以下の例は、 AWS Lambda の OS 環境情報やストレージの容量などを取得し、HTML 出力するコードです。

```python:lumbda_function.py
import subprocess

def lambda_handler(event, context):
    return_html="<HTML><TITLE>AWS Lambda Environment Information</TITLE><BODY>"
    return_html=return_html+"<h1>AWS Lambda Environment Information</h1>"

    return_html=return_html+"<h2>AWS Lambda Environmental Variables</h2>"
    cmd = ["env"]
    out = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode()
    return_html=return_html+out.replace('\n','<br>')

    return_html=return_html+"<h2>AWS Lambda Storage Information</h2>"
    cmd = ["df","-h"]
    out = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode()
    return_html=return_html+out.replace('\n','<br>')

    return_html=return_html+"<h2>AWS Lambda Directory Information</h2>"
    cmd = ["ls","-al", "/"]
    out = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode()
    return_html=return_html+out.replace('\n','<br>')

    return_html=return_html+"</BODY></HTML>"

    return return_html
```

保存したら、zip コマンドで圧縮します。

```sh
zip -r adcale.zip lambda_function.py 
```

コードを封入した zip ファイルと IAM ロール、その他設定を指定して、 ```lambda create-function``` コマンドで Lambda 関数を作成します。

```sh
aws lambda create-function --function-name adventcalendar2021 \
--role arn:aws:iam::<AwS アカウントID>:role/role-lambda-AdventCalendar2021 \
--zip-file fileb://adcale.zip \
--runtime python3.8 \
--handler lambda_function.lambda_handler
```

正常に関数の作成が行えると、以下のような json が返ってきます。

```json
{
    "FunctionName": "adventcalendar2021",
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:************:function:adventcalendar2021",
    "Runtime": "python3.8",
    "Role": "arn:aws:iam::************:role/role-lambda-AdventCalendar2021",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 470,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2021-12-22T07:55:07.710+0000",
    "CodeSha256": "********************************************",
    "Version": "$LATEST",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "********-****-****-****-************",
    "State": "Pending",
    "StateReason": "The function is being created.",
    "StateReasonCode": "Creating",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ]
}
```

## 動作確認

作成した Lambda 関数の動作確認をします。```lambda invoke``` コマンドを実行します。

```sh
aws lambda invoke --function-name adventcalendar202102 outfile
```

outfile にLambda 関数の return で指定した変数の内容が出力されます。
今回の例では、開業が入っておらず見づらいので、以下のように ```sed``` コマンドで見やすくします。

```sh
cat outfile | sed "s/>/>\n/g"
```

以下のような HTML 形式の内容が出力されれば成功です！

```sh
"<HTML>
<TITLE>
AWS Lambda Environment Information</TITLE>
<BODY>
<h1>
AWS Lambda Environment Information</h1>
<h2>
AWS Lambda Environmental Variables</h2>
AWS_LAMBDA_FUNCTION_VERSION=$LATEST<br>
(以下、略)
```

# まとめ
Lambda 関数の作成や実行も AWS CLI で簡単に行えてしまいました。
明日は、この Lambda 関数が出力する HTML を API Gateway から返すように設定していきます。