[JAWS-UG CLI] CloudWatch Events:#1 ビルトインイベントの実行


AWS CLIを利用して、CloudWatch EventsでEBSスナップショットを取得してみます。

注) このハンズオンはコンプリートできないことがわかってます。後日更新予定です。


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


CloudWatch Eventsへの権限
-------------------------

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


EC2への権限
-----------

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


AWS CLIのバージョン
-------------------

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

* AWS CLI 1.10.4

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

```text:結果(例):
aws-cli/1.10.4 Python/2.7.5 Darwin/13.4.0 botocore/1.3.26
```


IAMロール
---------

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

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

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

```json:結果(例)

      {
        "Role": {
          "AssumeRolePolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                  {
                      "Action": "sts:AssumeRole",
                      "Principal": {
                          "Service": "automation.amazonaws.com"
                      },
                      "Effect": "Allow",
                      "Sid": ""
                  }
              ]
          },
          "RoleId": "AROAXXXXXXXXXXXXXXXXX",
          "CreateDate": "2016-02-15T04:38:43Z",
          "RoleName": "AWSEventsActionsExecutionRole",
          "Path": "/",
          "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/AWSEventsActionsExecutionRole"
        }
      }
```


0. 準備
=======


0.1. リージョンの決定
---------------------

構築するリージョンを決めます。 (カレントユーザが利用するカレントリージ
ョンも切り変わります。)

```bash:コマンド(東京リージョンの場合):
export AWS_DEFAULT_REGION='ap-northeast-1'
```


0.2. 変数の確認
---------------

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

```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
```


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

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


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


1.1. EBSボリュームの確認
------------------------

```bash:コマンド:
aws ec2 describe-volumes
```

```json:結果(例):
      {
        "Volumes": [
          {
            "AvailabilityZone": "ap-northeast-1a",
            "Attachments": [],
            "Encrypted": false,
            "VolumeType": "standard",
            "VolumeId": "vol-xxxxxxxx",
            "State": "available",
            "SnapshotId": "",
            "CreateTime": "2016-02-15T04:01:51.884Z",
            "Size": 5
          }
        ]
      }
```


1.2. EBSボリュームの作成
------------------------

ボリュームが存在しない場合は、作成します。

作成できるAZを調べます。

```bash:コマンド:
aws ec2 describe-availability-zones
```

```json:結果(例):
      {
        "AvailabilityZones": [
          {
            "State": "available",
            "RegionName": "ap-northeast-1",
            "Messages": [],
            "ZoneName": "ap-northeast-1a"
          },
          {
            "State": "available",
            "RegionName": "ap-northeast-1",
            "Messages": [],
            "ZoneName": "ap-northeast-1c"
          }
        ]
      }
```

```bash:変数の設定:
EC2_AZ_NAME='ap-northeast-1a'
EC2_IMAGE_SIZE='5'
```

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

        EC2_AZ_NAME:    ${EC2_AZ_NAME}
        EC2_IMAGE_SIZE: ${EC2_IMAGE_SIZE}

ETX
```

```bash:コマンド:
aws ec2 create-volume \
        --availability-zone ${EC2_AZ_NAME} \
        --size ${EC2_IMAGE_SIZE}
```

```json:結果(例):
      {
        "AvailabilityZone": "ap-northeast-1a",
        "Encrypted": false,
        "VolumeType": "standard",
        "VolumeId": "vol-xxxxxxxx",
        "State": "creating",
        "SnapshotId": "",
        "CreateTime": "2016-02-15T04:01:51.884Z",
        "Size": 5
      }
```

## 1.3. EBS Volume IDの取得

```bash:変数の設定:
EC2_VOLUME_ID=$( \
        aws ec2 describe-volumes \
          --query "Volumes[?State==\`available\` && AvailabilityZone==\`${EC2_AZ_NAME}\`]".VolumeId \
          --output text
      ) && echo ${EC2_VOLUME_ID}
```

```bash:変数の設定:
TARGET_AWS_SERVICE='ec2'
TARGET_RESOURCE='volume'
```


2. ルールの作成
===============


2.1. ルール名の指定
-------------------

```bash:変数の設定:
EVENTS_RULE_NAME='create-ebs-snapshot'
```

同名のルールが存在しないことを確認します。



```bash:コマンド:
aws events describe-rule \
        --name ${EVENTS_RULE_NAME}
```

```text:結果(例):
A client error (ResourceNotFoundException) occurred when calling the DescribeRule operation: Rule create-ebs-snapshot does not exist.
```


2.1. ルールの作成
-----------------

```bash:変数の設定:
EVENTS_RULE_DESC='Create ebs snapshot.'
EVENTS_RULE_STATE='DISABLED'
EVENTS_SCHE_EXPRESSION='rate(5 minutes)'
```

```bash:変数の設定:
FILE_INPUT="${EVENTS_RULE_NAME}.json" \
        && echo ${FILE_INPUT}
```

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

        EVENTS_RULE_NAME:        ${EVENTS_RULE_NAME}
        EVENTS_RULE_DESC:       "${EVENTS_RULE_DESC}"
        EVENTS_RULE_STATE:       ${EVENTS_RULE_STATE}
        EVENTS_SCHE_EXPRESSION:  ${EVENTS_SCHE_EXPRESSION}
        FILE_INPUT:              ${FILE_INPUT}
        IAM_ROLE_ARN:            ${IAM_ROLE_ARN}
}

ETX
```

```bash:コマンド:
cat << EOF > ${FILE_INPUT}
{
          "Name": "${EVENTS_RULE_NAME}", 
          "ScheduleExpression": "${EVENTS_SCHE_EXPRESSION}", 
          "State": "${EVENTS_RULE_STATE}", 
          "Description": "${EVENTS_RULE_DESC}",
          "RoleArn": "${IAM_ROLE_ARN}"
}
EOF
cat ${FILE_INPUT}
```

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

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

エラーが出力されなければOKです。

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

        FILE_INPUT: ${FILE_INPUT}

ETX
```

```bash:コマンド(cli-input-json):
aws events put-rule \
        --cli-input-json file://${FILE_INPUT}
```

```json:結果(例):
      {
        "RuleArn": "arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/create-ebs-snapshot"
      }
```


2.2. ルールの確認
-----------------

```bash:コマンド:
aws events list-rules 
```

```json:結果(例):
      {
          "Rules": []
      }
```

```bash:コマンド:
aws events list-rules 
```

```json:結果(例):
      {
        "Rules": [
          {
              "State": "DISABLED",
              "ScheduleExpression": "rate(5 minutes)",
              "Name": "|EVENTS_RULE_NAME|",
              "Arn": "arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/create-ebs-snapshot",
              "Description": "Create ebs snapshot."
          }
        ]
      }
```

```bash:コマンド:
aws events describe-rule \
        --name ${EVENTS_RULE_NAME}
```

```json:結果(例):
      {
        "ScheduleExpression": "rate(5 minutes)",
        "Name": "create-ebs-snapshot",
        "State": "DISABLED",
        "Arn": "arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/create-ebs-snapshot",
        "Description": "create-ebs-snapshot"
      }
```


3. ターゲットの作成
===================


3.1. ターゲットIDの指定
-----------------------

```bash:変数の設定:
EVENTS_TARGET_ID='Id1'
```

同Idのターゲット名が存在しないことを確認します。

```bash:コマンド:
aws events list-targets-by-rule \
        --rule ${EVENTS_RULE_NAME} \
        --query "Targets[?Id==\`${EVENTS_TARGET_ID}\`]"
```

```json:結果(例):
      []
```



3.2. ターゲットの作成
---------------------

```bash:コマンド
AWS_ID=$( \
        aws iam get-role \
          --role-name ${IAM_ROLE_NAME} \
          --query 'Role.Arn' \
          --output text | \
          sed 's/^.*:://' | \
          sed 's/:.*$//' \
      ) \
        && echo ${AWS_ID}
```

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

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

        AWS_ID:             ${AWS_ID}
        TARGET_AWS_SERVICE: ${TARGET_AWS_SERVICE}
        AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
        TARGET_RESOURCE:    ${TARGET_RESOURCE}
        EC2_VOLUME_ID:     ${EC2_VOLUME_ID}

ETX
```

```bash:変数の設定:
EVENTS_TARGET_INPUT="arn:aws:${TARGET_AWS_SERVICE}:${AWS_DEFAULT_REGION}:${AWS_ID}:${TARGET_RESOURCE}/${EC2_VOLUME_ID}" \
        && echo ${EVENTS_TARGET_INPUT}
```

```bash:変数の設定:
EVENTS_TARGET_ARN="arn:aws:automation:${AWS_DEFAULT_REGION}:${AWS_ID}:action/EBSCreateSnapshot/EBSCreateSnapshot_create-ebs-snapshot" \
        && echo ${EVENTS_TARGET_ARN}
```

```bash:変数の設定:
FILE_INPUT="${EVENTS_RULE_NAME}-${EVENTS_TARGET_ID}.json" \
        && echo ${FILE_INPUT}
```

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

        FILE_INPUT:          ${FILE_INPUT}
        EVENTS_RULE_NAME:    ${EVENTS_RULE_NAME}
        EVENTS_TARGET_ID:    ${EVENTS_TARGET_ID}
        EVENTS_TARGET_INPUT: ${EVENTS_TARGET_INPUT}
        EVENTS_TARGET_ARN:   ${EVENTS_TARGET_ARN}

ETX
```

```bash:コマンド:
cat << EOF > ${FILE_INPUT}
{
          "Rule": "${EVENTS_RULE_NAME}", 
          "Targets": [
              {
                  "Input": "\"${EVENTS_TARGET_INPUT}\"",
                  "Id": "${EVENTS_TARGET_ID}", 
                  "Arn": "${EVENTS_TARGET_ARN}"
              }
          ]
}
EOF
cat ${FILE_INPUT}
```

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

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

エラーが出力されなければOKです。

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

        FILE_INPUT: ${FILE_INPUT}

ETX
```

```bash:コマンド(cli-input-json):
aws events put-targets \
        --cli-input-json file://${FILE_INPUT}
```

```json:結果(例):

      {
        "FailedEntries": [],
        "FailedEntryCount": 0
      }
```


3.3. ターゲットの確認
---------------------

```bash:コマンド:
aws events list-targets-by-rule \
        --rule ${EVENTS_RULE_NAME}
```

```json:結果(例):
      {
        "Targets": [
          {
              "Input": ""arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:volume/vol-xxxxxxxx"",
              "Id": "Id1",
              "Arn": "arn:aws:automation:ap-northeast-1:XXXXXXXXXXXX:action/EBSCreateSnapshot/EBSCreateSnapshot_test"
          }
        ]
      }
```

```bash:コマンド:
aws events list-rule-names-by-target \
        --target-arn ${EVENTS_TARGET_ARN}
```

```json:結果(例):
      {
        "RuleNames": [
          "create-ebs-snapshot"
        ]
      }
```


4. ルールの有効化/無効化
========================


4.1. ルールの有効化
-------------------

```bash:コマンド:
aws ec2 describe-snapshots \
        --owner-ids ${AWS_ID}
```

```json:結果(例):
      {
        "Snapshots": []
      }
```

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

        EVENTS_RULE_NAME: ${EVENTS_RULE_NAME}

ETX
```

```bash:コマンド:
aws events enable-rule \
        --name ${EVENTS_RULE_NAME}
```

```text:結果(例):
(戻り値なし)
```

```bash:コマンド:
aws ec2 describe-snapshots \
        --owner-ids ${AWS_ID}
```

```json:結果(例):
      {
        "Snapshots": []
      }
```


4.2. ルールの無効化
-------------------

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

        EVENTS_RULE_NAME: ${EVENTS_RULE_NAME}

ETX
```

```bash:コマンド:
aws events disable-rule \
        --name ${EVENTS_RULE_NAME}
```

```text:結果(例):
      (戻り値なし)
```


5. 後始末
=========


5.1. スナップショットの削除
---------------------------

```bash:変数の宣言:
EC2_SNAPSHOT_ID=$( \
        aws ec2 describe-snapshots \
          --owner-ids ${AWS_ID} \
          --query "Snapshots[?VolumeId==\`${EC2_VOLUME_ID}\`].SnapshotId" \
          --output text \
      ) && echo ${EC2_SNAPSHOT_ID}
```

```bash:コマンド:
aws ec2 delete-snapshot \
        --snapshot-id ${EC2_SNAPSHOT_ID}
```

```text:結果(例):
      (戻り値なし)
```

```bash:変数の宣言:
EC2_SNAPSHOT_ID=$( \
        aws ec2 describe-snapshots \
          --owner-ids ${AWS_ID} \
          --query "Snapshots[?VolumeId==\`${EC2_VOLUME_ID}\`].SnapshotId" \
          --output text \
      ) && echo ${EC2_SNAPSHOT_ID}
```

```text:結果(例):
      (戻り値なし)
```


5.2. EBSボリュームの削除
------------------------

```bash:コマンド:
aws ec2 describe-volumes \
        --volume-ids ${EC2_VOLUME_ID}
```

```json:結果(例):
      {
        "Volumes": [
          {
            "AvailabilityZone": "ap-northeast-1a",
            "Attachments": [],
            "Encrypted": false,
            "VolumeType": "standard",
            "VolumeId": "vol-xxxxxxxx",
            "State": "available",
            "SnapshotId": "",
            "CreateTime": "2016-02-15T04:01:51.884Z",
            "Size": 5
          }
        ]
      }
```

```bash:コマンド:
aws ec2 delete-volume \
        --volume-id ${EC2_VOLUME_ID}
```

```text:結果(例):
      (戻り値なし)
```

```bash:コマンド:
aws ec2 describe-volumes \
        --volume-ids ${EC2_VOLUME_ID}
```

```text:結果(例):
      A client error (InvalidVolume.NotFound) occurred when calling the DescribeVolumes operation: The volume 'vol-xxxxxxxx' does not exist.
```


5.3. ターゲットの削除
---------------------

```bash:コマンド:
aws events list-targets-by-rule \
        --rule ${EVENTS_RULE_NAME} \
        --query "Targets[?Id==\`${EVENTS_TARGET_ID}\`]"
```

```json:結果(例):
      [
        {
          "Input": "\"arn:aws:ec2:ap-northeast-1:XXXXXXXXXXXX:volume/vol-xxxxxxxx\"",
          "Id": "Id1",
          "Arn": "arn:aws:automation:ap-northeast-1:XXXXXXXXXXXX:action/EBSCreateSnapshot/EBSCreateSnapshot_create-ebs-snapshot"
        }
      ]
```

```bash:変数の設定:
ARRAY_EVENTS_TARGET_IDS="${EVENTS_TARGET_ID}"
```

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

        EVENTS_RULE_NAME:         ${EVENTS_RULE_NAME}
        ARRAY_EVENTS_TARGET_IDS: "${ARRAY_EVENTS_TARGET_IDS}"

ETX
```

```bash:コマンド:

      aws events remove-targets \
        --rule ${EVENTS_RULE_NAME} \
        --ids "${ARRAY_EVENTS_TARGET_IDS}"
```

```json:結果(例):
      {
        "FailedEntries": [],
        "FailedEntryCount": 0
      }
```

```bash:コマンド:

      aws events list-targets-by-rule \
        --rule ${EVENTS_RULE_NAME}
```

```json:結果(例):
      {
        "Targets": []
      }
```


5.4. ルールの削除
-----------------

```bash:コマンド:

      aws events describe-rule \
        --name ${EVENTS_RULE_NAME}
```

```json:結果(例):
      {
        "ScheduleExpression": "rate(5 minutes)",
        "Name": "create-ebs-snapshot",
        "State": "DISABLED",
        "Arn": "arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/create-ebs-snapshot",
        "Description": "create-ebs-snapshot"
      }
```

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

        EVENTS_RULE_NAME: ${EVENTS_RULE_NAME}

ETX
```

```bash:コマンド:
aws events delete-rule \
        --name ${EVENTS_RULE_NAME}
```

```text:結果(例):
      (戻り値なし)
```


# 完了