[JAWS-UG CLI] Lambda:#10 GetHelloWithName関数




前提条件
========


Lambdaへの権限
--------------

Lambdaに対してフル権限があること。


CloudWatchへの権限 (任意)
------------------------

CloudWatchに対してRead権限があること。


AWS CLI
-------

以下のバージョンで動作確認済

* AWS CLI 1.9.8

```bash:コマンド:
aws --version
```

結果(例):

      aws-cli/1.9.8 Python/2.7.5 Darwin/13.4.0 botocore/1.3.0


IAM Role
--------

'APIGatewayLambdaExecRole'ロールが存在すること。

```bash:変数の設定:
IAM_ROLE_NAME='APIGatewayLambdaExecRole'
```

```bash:コマンド:
aws iam get-role \
         --role-name ${IAM_ROLE_NAME}
```

```json:結果(例):
 {
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17", 
            "Statement": [
                {
                    "Action": "sts:AssumeRole", 
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    }, 
                    "Effect": "Allow", 
                    "Sid": ""
                }
            ]
        }, 
        "RoleId": "AROAIVVXU3HK5OJRHAGME", 
        "CreateDate": "2015-11-21T05:23:15Z", 
        "RoleName": "APIGatewayLambdaExecRole", 
        "Path": "/", 
         "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole"
    }
}
```

存在しない場合は、以下の手順で作成します。 

* http://qiita.com/tcsh/items/d62ab7697a1d437805b4


0. 準備
=======


0.1. 変数の確認
---------------

プロファイルが想定のものになっていることを確認します。

```bash:変数の確認:
aws configure list
```

```text:結果(例):
            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile       administrator-prjz-mbp13        env    AWS_DEFAULT_PROFILE
      access_key     ****************XXXX shared-credentials-file
      secret_key     ****************XXXX shared-credentials-file
          region                ap-northeast-1        env    AWS_DEFAULT_REGION
```

プロファイルが想定のものになっていることを確認します。



1. 事前作業
===========


1.1. Lambda関数名の決定
-----------------------

```bash:変数の設定:
LAMBDA_FUNC_NAME='GetHelloWithName'
```

同名のLambda関数の不存在確認

```bash:コマンド:
aws lambda get-function \
  --function-name ${LAMBDA_FUNC_NAME}
```

```text:結果(例):
A client error (ResourceNotFoundException) occurred when calling the GetFunction operation: Function not found: arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName
```


1.2. IAM RoleのARN取得
----------------------

```bash:変数の設定:
IAM_ROLE_NAME='APIGatewayLambdaExecRole'
```

```bash:コマンド:
IAM_ROLE_ARN=$( \
  aws iam get-role \
    --role-name ${IAM_ROLE_NAME} \
    --query 'Role.Arn' \
    --output text \
) \
  && echo ${IAM_ROLE_ARN}
```

```text:結果(例):
arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole'
```



1.3. Lambda関数
---------------

```bash:変数の設定:
FILE_LAMBDA_FUNC="${LAMBDA_FUNC_NAME}.js"
```

```bash:変数の確認:
cat << ETX

  FILE_LAMBDA_FUNC: ${FILE_LAMBDA_FUNC}

ETX
```

```bash:コマンド:
cat << EOF > ${FILE_LAMBDA_FUNC}
console.log('Loading event');
            
exports.handler = function(event, context) {
  var name = (event.name === undefined ? 'No-Name' : event.name);
  context.done(null, {"Hello":name}); // SUCCESS with message
};
EOF

cat ${FILE_LAMBDA_FUNC}
```

```bash:コマンド:
zip ${LAMBDA_FUNC_NAME}.zip ${FILE_LAMBDA_FUNC}
```

```text:結果:
  adding: GetHelloWithName.js (deflated 23%)
```


2. Lambda関数の作成
===================

```bash:変数の設定:
LAMBDA_FUNC_DESC='Return {"Hello":", a user-provided string, and "}'
LAMBDA_RUNTIME='nodejs'
LAMBDA_HANDLER="${LAMBDA_FUNC_NAME}.handler"
FILE_LAMBDA_FUNC="${LAMBDA_FUNC_NAME}.zip"
```

```bash:変数の確認:
cat << ETX

  LAMBDA_FUNC_NAME:  ${LAMBDA_FUNC_NAME}
  LAMBDA_FUNC_DESC:  "${LAMBDA_FUNC_DESC}"
  LAMBDA_RUNTIME:    ${LAMBDA_RUNTIME}
  FILE_LAMBDA_FUNC   ${FILE_LAMBDA_FUNC}
  IAM_ROLE_ARN:      ${IAM_ROLE_ARN}
  LAMBDA_HANDLER:    ${LAMBDA_HANDLER}

ETX
```

```bash:コマンド:
aws lambda create-function \
  --function-name ${LAMBDA_FUNC_NAME} \
  --description "${LAMBDA_FUNC_DESC}" \
  --zip-file fileb://${FILE_LAMBDA_FUNC} \
  --runtime ${LAMBDA_RUNTIME} \
  --role ${IAM_ROLE_ARN} \
  --handler ${LAMBDA_HANDLER}
```

```json:結果(例):
{
    "CodeSha256": "Z8neCCyJvNv5w8ogzXXJaYcqZybyZ10l72ZpSgAXL5U=", 
    "FunctionName": "GetHelloWithName", 
    "CodeSize": 348, 
    "MemorySize": 128, 
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName", 
    "Version": "$LATEST", 
    "Role": "arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole", 
    "Timeout": 3, 
    "LastModified": "2015-11-21T06:15:32.932+0000", 
    "Handler": "GetHelloWithName.handler", 
    "Runtime": "nodejs", 
    "Description": "Return {\"Hello\":\", a user-provided string, and \"}"
}
```

```bash:コマンド:
aws lambda list-functions 
```

```json:結果(例):
    "Functions": [
        {
            "Version": "$LATEST", 
            "CodeSha256": "Z8neCCyJvNv5w8ogzXXJaYcqZybyZ10l72ZpSgAXL5U=", 
            "FunctionName": "GetHelloWithName", 
            "MemorySize": 128, 
            "CodeSize": 348, 
            "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName", 
            "Handler": "GetHelloWithName.handler", 
            "Role": "arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole", 
            "Timeout": 3, 
            "LastModified": "2015-11-21T06:15:32.932+0000", 
            "Runtime": "nodejs", 
            "Description": "Return {\"Hello\":\", a user-provided string, and \"}"
        }
    ]
}
```

```bash:コマンド:
aws lambda get-function \
  --function-name ${LAMBDA_FUNC_NAME}
```

```json:結果(例):
{
    "Code": {
        "RepositoryType": "S3", 
        "Location": "https://awslambda-ap-ne-1-tasks.s3-ap-northeast-1.amazonaws.com/snapshots/XXXXXXXXXXXX/GetHelloWithName-c5c27bb6-6504-42bd-a782-2a1fe6f1f8a1?x-amz-security-token=AQoDYXdzEM%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEa4AOWzck3OEBkzPwLVKKnBOKajkInNbfoqn8HSqQfpIlpCctdzsS3MjEAGhW4o%2BZDTJOfTo76ytDBgP%2FtlqxTwGRg0rkea0b245ohKbw1ZevkbK0QRwdameBe3uRGuj%2FoYRXtT81Be7gbxOwQkIwl%2BM8JlAg6MjMVnKa7iiS%2Be5grfn%2FYnSptmuaxvuz1Zb8%2B2FnTUdeVACNddn5Y13FAVExk7KCh3QrYPbIOoKUKf4w1ASM%2BEztOLP5erCP0HWnYgHsLnOLbVgswxMHf7w4%2Br3TVAD0WxkxvYBWuo890onxoW3zA9mmrmXfvmMzhLucX89S7yI27qtRjaY64Ls5MNOa%2B4FDfnhJIM7gDEV8bQ%2BOAgvECBIO2GAAtUdsdqLw4b9XnhAzQIlSPg3fF1EVReqRSW5H0mZFC%2B1noH%2BVwyEvW5J2X0lI15GaglDV2cR6yUe9fXPgwPjXf1rclHvcTPDT02njvTY6jnAZIJnNOBPT4sbLX%2BoYx80Z9QESXFkKTHpmffL8ooXEBBsbRXLnaUV%2BEOgDwM5xUW%2FdrAob8hYvFGXOWD%2FAaULQABIIa%2FWa3mq7IhCR0dDX26lUDwDbrYaHLbjK4FQHwFqra0J9sAyXOaSiKV3XQSGRdAsVzFXke56Ugg4PAsgU%3D&AWSAccessKeyId=ASIAIG53ESD3CTGDEL6A&Expires=1448087243&Signature=SMwqPvvl%2FuJ7343GrfV0lxAaLsY%3D"
    }, 
    "Configuration": {
        "Version": "$LATEST", 
        "CodeSha256": "Z8neCCyJvNv5w8ogzXXJaYcqZybyZ10l72ZpSgAXL5U=", 
        "FunctionName": "GetHelloWithName", 
        "MemorySize": 128, 
        "CodeSize": 348, 
        "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName", 
        "Handler": "GetHelloWithName.handler", 
        "Role": "arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole", 
        "Timeout": 3, 
        "LastModified": "2015-11-21T06:15:32.932+0000", 
        "Runtime": "nodejs", 
        "Description": "Return {\"Hello\":\", a user-provided string, and \"}"
    }
}
```

```bash:コマンド:
aws lambda get-function-configuration \
  --function-name ${LAMBDA_FUNC_NAME}
```

```json:結果(例):
{
    "CodeSha256": "Z8neCCyJvNv5w8ogzXXJaYcqZybyZ10l72ZpSgAXL5U=", 
    "FunctionName": "GetHelloWithName", 
    "CodeSize": 348, 
    "MemorySize": 128, 
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName", 
    "Version": "$LATEST", 
    "Role": "arn:aws:iam::XXXXXXXXXXXX:role/APIGatewayLambdaExecRole", 
    "Timeout": 3, 
    "LastModified": "2015-11-21T06:15:32.932+0000", 
    "Handler": "GetHelloWithName.handler", 
    "Runtime": "nodejs", 
    "Description": "Return {\"Hello\":\", a user-provided string, and \"}"
}
```


# 3. Lambda関数の動作確認 (サンプルイベントなし)

3.1. lambda関数の手動実行
-------------------------

```bash:変数の設定:
FILE_OUTPUT_LAMBDA="${LAMBDA_FUNC_NAME}-out.txt"
FILE_LOG_LAMBDA="${LAMBDA_FUNC_NAME}-$(date +%Y%m%d%H%M%S).log"
```

```bash:変数の確認:
cat << ETX

  LAMBDA_FUNC_NAME:   ${LAMBDA_FUNC_NAME}
  FILE_OUTPUT_LAMBDA: ${FILE_OUTPUT_LAMBDA}
  FILE_LOG_LAMBDA:    ${FILE_LOG_LAMBDA}

ETX
```

```bash:コマンド:
aws lambda invoke \
  --function-name ${LAMBDA_FUNC_NAME} \
  --log-type Tail \
  ${FILE_OUTPUT_LAMBDA} \
  > ${FILE_LOG_LAMBDA}
```

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} | \
  jq -r '.StatusCode'
```

```text:結果(例):
200
```


3.3. lambda関数の実行結果の確認
-------------------------------

```bash:コマンド:
cat ${FILE_OUTPUT_LAMBDA}
```

```text:結果:
{"Hello":"No-Name"}
```


3.4. lambda関数のログの確認
---------------------------

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} | \
  jq -r '.LogResult' | \
  base64 --decode
```

```text:結果:
START RequestId: c18e51a2-9019-11e5-ac3d-0feeb354af40 Version: $LATEST
END RequestId: c18e51a2-9019-11e5-ac3d-0feeb354af40
REPORT RequestId: c18e51a2-9019-11e5-ac3d-0feeb354af40	Duration: 0.42 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 27 MB
```

# 4. Lambda関数の動作確認 (サンプルイベントあり)

## 4.1. サンプルイベントデータの作成

```bash:変数の設定:
FILE_DATA_LAMBDA="${LAMBDA_FUNC_NAME}-data.json" \
  && echo ${FILE_DATA_LAMBDA}
```

```bash:サンプルデータ:
cat << EOF > ${FILE_DATA_LAMBDA}
{
  "name": "User"       
}
EOF

cat ${FILE_DATA_LAMBDA}
```

```bash:コマンド:
jsonlint -q ${FILE_DATA_LAMBDA}
```


4.2. lambda関数の手動実行
-------------------------

```bash:変数の設定:
FILE_OUTPUT_LAMBDA="${LAMBDA_FUNC_NAME}-out.txt"
FILE_LOG_LAMBDA="${LAMBDA_FUNC_NAME}-$(date +%Y%m%d%H%M%S).log"
```

```bash:変数の確認:
cat << ETX

  LAMBDA_FUNC_NAME:   ${LAMBDA_FUNC_NAME}
  FILE_DATA_LAMBDA:   ${FILE_DATA_LAMBDA}
  FILE_OUTPUT_LAMBDA: ${FILE_OUTPUT_LAMBDA}
  FILE_LOG_LAMBDA:    ${FILE_LOG_LAMBDA}

ETX
```

```bash:コマンド:
aws lambda invoke \
  --function-name ${LAMBDA_FUNC_NAME} \
  --log-type Tail \
  --payload file://${FILE_DATA_LAMBDA} \
  ${FILE_OUTPUT_LAMBDA} \
  > ${FILE_LOG_LAMBDA}
```

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} | \
  jq -r '.StatusCode'
```

```text:結果(例):
200
```


4.3. lambda関数の実行結果の確認
-------------------------------

```bash:コマンド:
cat ${FILE_OUTPUT_LAMBDA}
```

```text:結果:
{"Hello":"User"}
```


4.4. lambda関数のログの確認
---------------------------

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} | \
  jq -r '.LogResult' | \
  base64 --decode
```

```text:結果:
START RequestId: 6efb0e8f-9018-11e5-9a79-e33dc551d93f Version: $LATEST
END RequestId: 6efb0e8f-9018-11e5-9a79-e33dc551d93f
REPORT RequestId: 6efb0e8f-9018-11e5-9a79-e33dc551d93f	Duration: 1.38 ms	Billed Duration: 100 ms 	Memory Size: 128 MB	Max Memory Used: 27 MB
```


# 5. CloudWatchの確認 (任意)

```bash:変数の設定:
CWATCH_NAMESPACE=AWS/Lambda
CWATCH_METRIC_NAME='Invocations'
CWATCH_DIMENSIONS="Name=FunctionName,Value=${LAMBDA_FUNC_NAME}"
```

```bash:コマンド:
aws cloudwatch list-metrics \
  --namespace ${CWATCH_NAMESPACE} \
  --metric-name ${CWATCH_METRIC_NAME} \
  --dimensions ${CWATCH_DIMENSIONS}
```

```json:結果(例):
{
    "Metrics": [
        {
            "Namespace": "AWS/Lambda", 
            "Dimensions": [
                {
                    "Name": "FunctionName", 
                    "Value": "GetHelloWithName"
                }
            ], 
            "MetricName": "Invocations"
        }, 
        {
            "Namespace": "AWS/Lambda", 
            "Dimensions": [
                {
                    "Name": "Resource", 
                    "Value": "GetHelloWithName"
                }, 
                {
                    "Name": "FunctionName", 
                    "Value": "GetHelloWithName"
                }
            ], 
            "MetricName": "Invocations"
        }
    ]
}
```

```bash:コマンド:
CWATCH_STAT_PERIOD='300'
CWATCH_STATISTICS='SampleCount'
```

```bash:コマンド:
CWATCH_END_TIME=`date -u '+%FT%TZ'` \
  && echo ${CWATCH_END_TIME}
TIME_BEFORE_MIN='1440'
```

```bash:コマンド(OSX/BSD系OSの場合):
CWATCH_START_TIME=`date -u -v-${TIME_BEFORE_MIN}M '+%FT%TZ'` \
  && echo ${CWATCH_START_TIME}
```

```bash:コマンド(Linux系OSの場合):
CWATCH_START_TIME=`date -u -d "${TIME_BEFORE_MIN} mins ago" '+%FT%TZ'` \
  && echo ${CWATCH_START_TIME}
```

```bash:コマンド:
cat << ETX

        CWATCH_NAMESPACE:   ${CWATCH_NAMESPACE}
        CWATCH_METRIC_NAME: ${CWATCH_METRIC_NAME}
        CWATCH_START_TIME:  ${CWATCH_START_TIME}
        CWATCH_END_TIME:    ${CWATCH_END_TIME}
        CWATCH_STAT_PERIOD: ${CWATCH_STAT_PERIOD}
        CWATCH_STATISTICS:  ${CWATCH_STATISTICS}

ETX
```

```bash:コマンド:
aws cloudwatch get-metric-statistics \
        --namespace ${CWATCH_NAMESPACE} \
        --metric-name ${CWATCH_METRIC_NAME} \
        --start-time ${CWATCH_START_TIME} \
        --end-time ${CWATCH_END_TIME} \
        --period ${CWATCH_STAT_PERIOD} \
        --statistics ${CWATCH_STATISTICS}
```

```json:結果(例):
{
    "Datapoints": [
        {
            "SampleCount": 1.0, 
            "Timestamp": "2015-11-21T06:22:00Z", 
            "Unit": "Count"
        }
    ], 
    "Label": "Invocations"
}
```


完了
====