AWS CLIでput-bucket-notification-configurationするときにjqで既存の設定と追加差分を上手いことマージする

# 概要

CLIでの`put-bucket-notification-configuration`について、差分でのputを実施。
(もう少し汎用化できるようにも思うが、自分用としては`notification-configuration`で対象を特定する形で良しとする。)

# やりたいこと

- aws cliベースで作業手順を作成している
- S3へLambdaを発火させるイベントを追加するため、s3apiの`put-bucket-notification-configuration`を使用した
- putなので既に存在していた設定が上書きされてしまった
    - 差分ベースの手順作成が難しい
    - 元の設定消えるので普通に事故
- **CLIだけで上手いこと差分をマージしたい！**

# やったこと

- `--notification-configuration`オプションで特定の設定だけを更新するようにした。
    - ここでは`LambdaFunctionConfigurations`
- jqを使って上手いことマージした。

# 必要なもの

- jq
    - windows10で作業したがmac OSでもできることが望ましい
- aws cli
    - 言わずもがな
- git bash
    - windows環境でshellを叩きたいので。shellが使えれば何でも。

# 手順

## 1. 対象のJSONをgetしてファイルへ出力する

```shell:get
# 対象のバケット
TARGET_BUCKET=bucket-foo
aws s3api get-bucket-notification-configuration --bucket ${TARGET_BUCKET} > get-bucket-notification-configuration.json
```

### 例

Lambdaを発火させるイベント追加の場合
->既にsomethingEventAが設定済み

```json:get-bucket-notification-configuration.json
{
  "LambdaFunctionConfigurations": [
    {
      "Id": "somethingEventA",
      "LambdaFunctionArn": "arn:aws:lambda:xxxxxxxxx",
      "Events": [
        "s3:ObjectCreated:Put"
      ],
      "Filter": {
        "Key": {
          "FilterRules": [
            {
              "Name": "prefix",
              "Value": "foo/bar/"
            },
            {
              "Name": "suffix",
              "Value": ".zip"
            }
          ]
        }
      }
    }
  ]
}
```

## 2. マージしたい差分ファイルを用意する

`--notification-configuration`オプションを利用ように構成する

### 例

Lambdaを発火させるイベント追加の場合
新たに追加したいsomethingEventBを用意

```json:diff-sample.json
{
  "LambdaFunctionConfigurations": [
    {
      "Id": "somethingEventB",
      "LambdaFunctionArn": "arn:aws:lambda:xxxxxxxxx",
      "Events": [
        "s3:ObjectCreated:Put"
      ],
      "Filter": {
        "Key": {
          "FilterRules": [
            {
              "Name": "prefix",
              "Value": "foo/bar/"
            },
            {
              "Name": "suffix",
              "Value": ".csv"
            }
          ]
        }
      }
    }
  ]
}
```

## 3. 2つのファイルをマージ

### 例

Lambda関数を送信先にする場合(=`LambdaFunctionConfigurations`をマージする場合)

```shell:merge
# マージ対象のオブジェクトを指定
TARGET_OBJECT=LambdaFunctionConfigurations
# オブジェクトを指定してマージ
cat get-bucket-notification-configuration.json notification.json | jq -s ".[0].${TARGET_OBJECT} + .[1].${TARGET_OBJECT} | {\"${TARGET_OBJECT}\": .}" > merge-notification.json
```

## 4. マージしたファイルをput

`--notification-configuration`オプションを利用

```shell:put
aws s3api put-bucket-notification-configuration --bucket ${TARGET_BUCKET} --notification-configuration file://merge-notification.json
```
## 結果

```shell:check
aws s3api get-bucket-notification-configuration --bucket ${TARGET_BUCKET}
```

```json:result
{
  "LambdaFunctionConfigurations": [
    {
      "Id": "somethingEventA",
      "LambdaFunctionArn": "arn:aws:xxxxxx",
      "Events": [
        "s3:ObjectCreated:Put"
      ],
      "Filter": {
        "Key": {
          "FilterRules": [
            {
              "Name": "Prefix",
              "Value": "foo/bar/"
            },
            {
              "Name": "Suffix",
              "Value": ".zip"
            }
          ]
        }
      }
    },
    {
      "Id": "somethingEventB",
      "LambdaFunctionArn": "arn:aws:xxxxxx",
      "Events": [
        "s3:ObjectCreated:Put"
      ],
      "Filter": {
        "Key": {
          "FilterRules": [
            {
              "Name": "prefix",
              "Value": "foo/bar/"
            },
            {
              "Name": "suffix",
              "Value": ".csv"
            }
          ]
        }
      }
    }
  ]
}
```

# 参考
- [aws s3api put-bucket-notification-configuration](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-notification-configuration.html)
- [aws s3api get-bucket-notification-configuration](https://docs.aws.amazon.com/cli/latest/reference/s3api/get-bucket-notification-configuration.html)
- [jq](https://stedolan.github.io/jq/)