AWSの勉強

# Lambdaの非同期呼び出し

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Serverless-3-2022-confirmation_772.html

### 利用するもの

- S3（ストレージ）
- Lambda（プログラムを記述・実行する場所）
- AWS AI Services (AWSが提供しているAIモデル)

### 非同期呼び出しの流れ

例：音声ファイルの文字起こしを行い、ファイルに変換

1. S3に音声ファイルをアップロード(トリガーとなる)
2. Lambdaが実行される
3. Lambdaのコードが呼び出したtranscribe(AWS AI Servicesの一つ)が実行される

### 非同期呼び出しの実装

上記の例を実装する流れ

1. 音声ファイルを入れてトリガーとなるS3(*1)と、生成されるファイルを格納するS3(*2)を作成．
2. lambda（関数）を作成する．
その際(*1)をトリガーに、出力場所を(*2)に設定する．（ロールにポリシーの追加も）
3. [ドキュメント](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/index.html)を参考にしてtranscribeのコードをlambdaに記述．
4. 完成．音声ファイルを(*1)に入れると自動で文字起こしが実行されて(*2)にjson形式で格納される．

# API Gatewayを使ってAPIを作成

https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-Serverless-1-2022-confirmation_422.html

例：入力した日本語を英語に翻訳するAPI

1. リソースを作成
2. リソースの中に統合タイプがlambda関数のGETメソッドを作成
API Gatewayからの入力・出力をパススルーさせるために、「lambdaプロキシ統合の使用」にチェックを入れる
3. 元の日本語テキストを入力するためのURLクエリ文字列パラメータを追加（必須にする）
4. Lambda関数を書く
    ~~~python
    import json
    import boto3
    
    translate = boto3.client('translate')
    
    def lambda_handler(event, context):
        # クエリパラメータから翻訳するテキストを読み取る
        input_text = event['queryStringParameters']['input_text']
        
        response = translate.translate_text(
            Text=input_text,
            SourceLanguageCode='ja', #元のテキストは日本語
            TargetLanguageCode='en', #翻訳後は英語
        )
        
        output_text = response.get('TranslatedText')
        
        return {
            'statusCode': 200,
            'body': json.dumps({
                'output_text': output_text
            }),
            'isBase64Encoded': False,
            'headers': {}
        }
        ~~~
5. デプロイ
6. 指定したステージを開くとURLが生成されており、URLの最後に`?input_text=こんばんは`を追加して開くと翻訳が返されたWebページが表示される

### 出力をDynamoDBに保存する場合

~~~python
import json
import boto3
import datetime

translate = boto3.client('translate')
# 出力を保存するDynamoDBを指定
dynamo_translate_history_tbl = boto3.resource('dynamodb').Table('translate-history')

def lambda_handler(event, context):
    # クエリパラメータから翻訳するテキストを読み取る
    input_text = event['queryStringParameters']['input_text']
    
    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode='ja', #元のテキストは日本語
        TargetLanguageCode='en', #翻訳後は英語
    )
    
    output_text = response.get('TranslatedText')
    
    # DynamoDBに追加
    dynamo_translate_history_tbl.put_item(
        Item = {
            'timestamp': datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
            'input_text': input_text,
            'output_text': output_text
        }
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        }),
        'isBase64Encoded': False,
        'headers': {}
    }
~~~

### ちなみにSAMテンプレートを使えば全部自動でやってくれる

SAMのビルド

~~~
sam init （最初だけ）
sam build
sam deploy --guided
~~~

ディレクトリ構造

~~~
environment
     |--- hands-on-serverless-2 
                    |--- translate-fuction
                    |         |--- translate-function.py
                    |--- template.yaml
~~~

~~~yaml:template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Hands-on for Beginners - Serverless 2
Resources:
  TranslateLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: translate-function-2 #
      CodeUri: ./translate-function
      Handler: translate-function.lambda_handler
      Runtime: python3.7
      Timeout: 5
      MemorySize: 256
      Policies:
        - TranslateFullAccess
        - AmazonDynamoDBFullAccess
      Events:
        GetApi:
          Type: Api
          Properties:
            Path: /translate
            Method: get
            RestApiId: !Ref TranslateAPI
  TranslateAPI:
    Type: AWS::Serverless::Api
    Properties:
      Name: translate-api-2
      StageName: dev
      EndpointConfiguration: REGIONAL
  TranslateDynamoDbTbl:
    Type: AWS::Serverless::SimpleTable
    Properties:
      TableName: translate-history-2
      PrimaryKey:
        Name: timestamp
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
~~~

s3生成コマンド

~~~
aws s3 mb s3://hands-on-serverless-2
~~~

TranslateやDBなどをローカルで利用するには、cloud9のEC2インスタンスにTranslateやDBなどの権限を与えたロールを追加する必要がある。
（cloud9ダッシュボード→EC2インスタンス→アクション→セキュリティ→IAMロールを変更→追加→…）

Lambda関数のローカル実行コマンド
~~~bash
# サーバーを立てる
sam local start-lambda
# 別のターミナル行ってビルド
sam build
# 実行
aws lambda invoke --function-name "TranslateLambda" --endpoint-url "http://127.0.0.1:3001" --no-verify-ssl out.txt
~~~
APIのローカル実行コマンド
~~~
# サーバーを立てる
sam local start-api
# 別のターミナル行ってビルド
sam build
# 実行
curl http://127.0.0.1:3000/translate?input_text='こんにちは'
~~~

API生成コマンド

~~~
aws cloudformation package --template-file template.yaml --s3-bucket hands-on-serverless-2 --output-template-file packaged-template.yaml
~~~

~~~
aws cloudformation deploy --template-file ./packaged-template.yaml --stack-name hands-on-serverless-2 --capabilities CAPABILITY_IAM
~~~

# AWS Amplify

↓全部ここ↓

https://docs.amplify.aws/start/q/integration/react/

基本的なバックエンド処理も認証機能もデプロイも、全部簡単なコマンドでできる。