[JAWS-UG CLI] Lambda:#1. Lambda関数の作成と実行

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


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

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


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

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


AWS CLI
-------

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

* AWS CLI 1.9.0

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

結果(例):

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


IAM Role
--------

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

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

```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": "AROAI2DMAFJEPZE7RBSUG",
          "CreateDate": "2015-10-26T01:55:54Z",
          "RoleName": "lambdaBasicExecution",
          "Path": "/",
          "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution"
        }
      }
```


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.0. IAM RoleのARN取得
----------------------

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

```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/lambdaBasicExecution'
```




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

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

同名の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:HelloWorld
```


1.2. 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 function');

exports.handler = function(event, context) {
        console.log('value1 =', event.key1);
        console.log('value2 =', event.key2);
        console.log('value3 =', event.key3);
        context.succeed(event.key1);  // Echo back the first key value
        // context.fail('Something went wrong');
};
EOF

cat ${FILE_LAMBDA_FUNC}
```

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

```text:結果:
      adding: HelloWorld.js (deflated 43%)
```


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

```bash:変数の設定:
LAMBDA_FUNC_DESC='A starter AWS Lambda function.'
LAMBDA_RUNTIME='nodejs'
LAMBDA_HANDLER="${LAMBDA_FUNC_NAME}.handler"
FILE_LAMBDA_ZIP="${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_ZIP    ${FILE_LAMBDA_ZIP}
        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_ZIP} \
        --runtime ${LAMBDA_RUNTIME} \
        --role ${IAM_ROLE_ARN} \
        --handler ${LAMBDA_HANDLER}
```

```json:結果(例):
      {
        "CodeSha256": "WnGd6iPBS0rGCJor4zyuOaGBtzQ3I/OgHerXWqZzbL8=",
        "FunctionName": "HelloWorld",
        "CodeSize": 350,
        "MemorySize": 128,
        "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:HelloWorld",
        "Version": "$LATEST",
        "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution",
        "Timeout": 3,
        "LastModified": "2015-10-26T02:08:11.949+0000",
        "Handler": "HelloWorld.handler",
        "Runtime": "nodejs",
        "Description": "A starter AWS Lambda function."
      }
```

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

```json:結果(例):
      {
        "Functions": [
          {
              "Version": "$LATEST",
              "CodeSha256": "WnGd6iPBS0rGCJor4zyuOaGBtzQ3I/OgHerXWqZzbL8=",
              "FunctionName": "HelloWorld",
              "MemorySize": 128,
              "CodeSize": 350,
              "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:HelloWorld",
              "Handler": "HelloWorld.handler",
              "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution",
              "Timeout": 3,
              "LastModified": "2015-10-26T02:08:11.949+0000",
              "Runtime": "nodejs",
              "Description": "A starter AWS Lambda function."
          }
        ]
      }
```

```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/HelloWorld-2979ba79-b08f-495d-9ee6-46397c95ba13?x-amz-security-token=AQoDYXdzEDoa8AMR6t8h66eOXhN3%2Fx7XpuRxvf7pVn7IuWV4cEmwx0CtZT6yxCJ1%2BWmigYXqGoyQHuBYOWnxbhmwEcTg839qMuhSu1fk0fXpXf0oJOLkhKMudNqhdElyFQpzyT6Q8GDfhAsfbX9wvwCDTty4imxz7MczF%2FQl6tgvTYdip08ap5fAyrknZGV1%2B1Ggnp5w6JOjydYxuUsWwhoxoEWzi7SoVTmpRQQA91c4VW9lNotOAHACFxo6klzDPM8mxR9RJl66WxFugL0wQJyLUpmtjS9XoArD86sEWWiIccMpV2BQipTPQlzL%2F1Hoy%2BDF6QUxyPUihlDjPBoJTISTP8W1wxmzW%2BLbilAfFQRPY7CFjzR0k%2FA%2FIX5x9iyz52Pu1Q0ASTw1l%2Fq%2Fo3pRbvzWR79QS%2BpxXrwbYzoQHKiK62DSTsQo5tqKPsiDCYzrPxbq8lm7pNBPG%2FsxjePRWBVJeRl08WxEjSjoRRwBOPX5mz1BCUoUBPGG5tEENp87A%2FCdDgibFWM5DdYhwtaYPY7FTmi8DvqjQHL9jOmP8YuVteBTBcv8nFW6UbErPjwwn79FKG1u5M9HoTWUqUMBByz6D4tTRSEw6iJU7XdCujFnhnHe5V8imZ1KGI7fDWpciJhrhml0wnKPCK%2Fe9lK1P2kO7ldSWc7zn5hcIOD2tbEF&AWSAccessKeyId=ASIAJFVALOKV5SJVYPPA&Expires=1445825978&Signature=bvwu1Ny34LgTmZeOO3q4sn7x3Fg%3D"
        },
        "Configuration": {
          "Version": "$LATEST",
          "CodeSha256": "WnGd6iPBS0rGCJor4zyuOaGBtzQ3I/OgHerXWqZzbL8=",
          "FunctionName": "HelloWorld",
          "MemorySize": 128,
          "CodeSize": 350,
          "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:HelloWorld",
          "Handler": "HelloWorld.handler",
          "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution",
          "Timeout": 3,
          "LastModified": "2015-10-26T02:08:11.949+0000",
          "Runtime": "nodejs",
          "Description": "A starter AWS Lambda function."
        }
      }
```

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

```json:結果(例):
      {
        "CodeSha256": "WnGd6iPBS0rGCJor4zyuOaGBtzQ3I/OgHerXWqZzbL8=",
        "FunctionName": "HelloWorld",
        "CodeSize": 350,
        "MemorySize": 128,
        "FunctionArn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:HelloWorld",
        "Version": "$LATEST",
        "Role": "arn:aws:iam::XXXXXXXXXXXX:role/lambdaBasicExecution",
        "Timeout": 3,
        "LastModified": "2015-10-26T02:08:11.949+0000",
        "Handler": "HelloWorld.handler",
        "Runtime": "nodejs",
        "Description": "A starter AWS Lambda function."
      }
```


3. Lambda関数の動作確認
=======================


3.1. サンプルデータの作成
-------------------------

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

```bash:サンプルデータ:
cat << EOF > ${FILE_DATA_LAMBDA}
{
          "key1": "val1",
          "key2": "val2",
          "key3": "val3"
}
EOF

cat ${FILE_DATA_LAMBDA}
```

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


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


```bash:変数の設定:
FILE_OUTPUT_LAMBDA="${LAMBDA_FUNC_NAME}-out.txt" \
        && echo ${FILE_OUTPUT_LAMBDA}
```

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

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

ETX
```

```bash:コマンド:
FILE_LOG_LAMBDA="${LAMBDA_FUNC_NAME}-$(date +%Y%m%d%H%M%S).log" \
        && echo ${FILE_LOG_LAMBDA}
```

```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} \
  | jp.py 'StatusCode'
```

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


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

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

```text:結果:
      "val1"
```


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

```bash:コマンド:
cat ${FILE_LOG_LAMBDA} \
        | jp.py 'LogResult' \
        | sed 's/"//' \
        | base64 --decode
```

```text:結果:
      START RequestId: 37887883-7b87-11e5-9ffa-7548aec1bfac Version: $LATEST
      2015-10-26T02:13:59.974Z    37887883-7b87-11e5-9ffa-7548aec1bfac    value1 = value1
      2015-10-26T02:13:59.974Z    37887883-7b87-11e5-9ffa-7548aec1bfac    value2 = value2
      2015-10-26T02:13:59.974Z    37887883-7b87-11e5-9ffa-7548aec1bfac    value3 = value3
      END RequestId: 37887883-7b87-11e5-9ffa-7548aec1bfac
      REPORT RequestId: 37887883-7b87-11e5-9ffa-7548aec1bfac      Duration: 12.08 ms      Billed Duration: 100 ms         Memory Size: 128 MB     Max Memory Used: 27 MB
```


3.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": "HelloWorld"
                  }
              ],
              "MetricName": "Invocations"
          },
          {
              "Namespace": "AWS/Lambda",
              "Dimensions": [
                  {
                      "Name": "Resource",
                      "Value": "HelloWorld"
                  },
                  {
                      "Name": "FunctionName",
                      "Value": "HelloWorld"
                  }
              ],
              "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-10-26T02:10:00Z",
              "Unit": "Count"
          }
        ],
        "Label": "Invocations"
      }
```


完了
====