【AWS】Python Lambdaのdeploy - CloudFormation

[【AWS】Python Lambdaのdeploy - CloudFormation - Qiita](https://qiita.com/sand/items/2b918a29bf08bfb86d32)
[【AWS】Python Lambdaのdeploy - Chalice - Qiita](https://qiita.com/sand/items/4642f417bf0d2b49c7e2)


**CloudFormation**を使えば、AWSの様々な設定やdeployを自動化できます。AWS Serverless Application Model (SAM) は、AWS が公式で提供しているサーバーレスアプリケーションのためのフレームワークです。Lambda, API Gateway, DynamoDB,Cognito,S3等、AWSのほとんどのリソースをひとまとめに管理 (作成 / 更新 / 削除) することができます。一部設定できない項目もあります。SAMはyamlファイルを書くことで定義できます。(JSONでも可能ですがここでは触れません)


**定刻に定型のメールを送信するLambda関数をdeployすることにします。**

#１．SAMファイル

まずは以下のようなyamlを書きます。Globalsで「**Runtime: python3.6**」を指定していることに注意してください。中にコメントしますので、コピペするときは削除してください。また**CloudWatch のEvents**でcronを定義し、スケジューラを設定することに注意してください。

```yaml:serverless.yml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Globals:
  Function:
    Runtime: python3.6   # PythonのLambda関数
    Timeout: 30
    Tracing: Active
    Environment:
      Variables:
        REGION: !Ref AWS::Region
Description: "Example template including Lambda"
Resources:
  amazonsessample:
    Type: AWS::Serverless::Function    # Lambdaのリソース
    Properties:
      Handler: amazonsessample.handler  # Handler
      Policies:
      - Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Action:
            - ses:SendEmail      # SESのSendEmailを使う
          Resource:
            - '*' 
      Events:                    # CloudWatch のEventsでcronを定義
        ScheduleEvent:
          Type: Schedule
          Properties:
            Schedule: cron(45 1 * * ? *)
```




#２．Lambda関数

ここでは次のドキュメントのソースを利用します。[「AWS SDK for Python (Boto) を使用して E メールを送信する - AWS公式ドキュメント」](https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/send-using-sdk-python.html)

PythonからAWSへアクセスするためには、[「AWS SDK for Python (Boto3) - AWS公式ドキュメント」](https://aws.amazon.com/jp/sdk-for-python/)というライブラリを使います。


```python:amazonsessample.py
import boto3
from botocore.exceptions import ClientError

def handler(event, context):
    print("#####",event)
    # -- SENDERとRECIPIENTのemailは予めSESでVerifyする必要がある
    SENDER = "Sender Name <verified-email1@gmail.com>"
    RECIPIENT = "verified-email2@gmail.com"

    AWS_REGION = "us-west-2"   # オレゴンを設定。SESでは東京は使えない。
    SUBJECT = "Amazon SES Test (SDK for Python)"

    BODY_TEXT = ("Amazon SES Test (Python)\r\n"
                 "This email was sent with Amazon SES using the "
                 "AWS SDK for Python (Boto)."
                )

    BODY_HTML = """<html>
<head></head>
<body>
  <h1>Amazon SES Test (SDK for Python)</h1>
  <p>This email was sent with
    <a href='https://aws.amazon.com/ses/'>Amazon SES</a> using the
    <a href='https://aws.amazon.com/sdk-for-python/'>
      AWS SDK for Python (Boto)</a>.</p>
</body>
</html>
"""    

    CHARSET = "UTF-8"
    client = boto3.client('ses',region_name=AWS_REGION)

    try:
        response = client.send_email(
            Destination={
                'ToAddresses': [
                    RECIPIENT,
                ],
            },
            Message={
                'Body': {
                    'Html': {
                        'Charset': CHARSET,
                        'Data': BODY_HTML,
                    },
                    'Text': {
                        'Charset': CHARSET,
                        'Data': BODY_TEXT,
                    },
                },
                'Subject': {
                    'Charset': CHARSET,
                    'Data': SUBJECT,
                },
            },
            Source=SENDER,
        )

    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        print("Email sent! Message ID:"),
        print(response['ResponseMetadata']['RequestId'])

    return 9    # 適当なreturn値
```


最後にboto3をインストールしておきましょう。

```
pip install boto3
```

#３．deployと削除

deployにはaws cloudformationを2つ打つだけなのですが、以下のようにshスクリプトにしておいた方が便利でしょう。ここで重要なのはstack-nameの指定です。deployはこのstack-nameのもとで行われます。またS3上にcf-template-xxxxxという（名前は任意）bucketをあらかじめ用意しておく必要があります。

```sh:go1.sh
#!/bin/bash -e
# *** deploy cloudformation yaml
aws cloudformation package --template-file serverless.yml --output-template-file serverless-output.yml --s3-bucket cf-template-xxxxx
aws cloudformation deploy --template-file serverless-output.yml --stack-name mystackname --capabilities CAPABILITY_IAM
```


deployした全てのリソースは、CloudFormationサービスでstack-nameを指定して、一括して削除できます。


今回は以上です。



#★最近の投稿
[【AWS】Pythonの開発環境Chaliceを使ってみる - アマゾン売れ筋ランキング](https://qiita.com/sand/items/cfdc9957caa0aee63c0f)
[【AWS】Pythonの開発環境Chaliceを使ってみる - CloudWatch Events](https://qiita.com/sand/items/4a4c273872b266af6680)
[【AWS】Pythonの開発環境Chaliceを使ってみる - API Key](https://qiita.com/sand/items/2f8615b03c6f24c85b49)
[【AWS】Python Lambdaのdeploy - Chalice](https://qiita.com/sand/items/4642f417bf0d2b49c7e2)
[【AWS】Python Lambdaのdeploy - CloudFormation](https://qiita.com/sand/items/2b918a29bf08bfb86d32)