AWS IoT Greengrass v2 のコンポーネント開発時に、レシピの設定変更が反映されない (ように見える) 時の Tips 

初歩的なつまづき感もありますが、備忘のためメモ。

## 課題

AWS IoT Greengrass のカスタムコンポーネントを開発していて、

- デバイス上でレシピファイルを更新
-  Greeengrass CLI で `greengrass-cli deployment create` を実行

という手順でコンポーネントの再デプロイをかけたにも関わらず、レシピから消したはずの設定内容がまだ効いてしまっている……ということで手詰まってしまっていました。

## 原因と対策 (サマリ)

- **原因** : コンポーネントのデプロイ時に、レシピの設定は過去のレシピから新しいレシピの設定に置き換わるのではなく、**新しいレシピの設定を古いレシピの設定にマージするから**
- **対策** : `greengrass-cli deployment create` の `--update-config` オプションで、設定値のリセットをかける
    - また、設定値の反映が疑わしいと感じたら、 `greengrass-cli component details` や `greengrass-cli component list` コマンドで現在適用されている設定値を確認する

※ 以下、 `com.examlple.HelloWorld` という文字列は全て自分自身の開発するコンポーネントの名前に置き換えてください。

### 対策の具体例 : CLI を実行する際のホームディレクトリに以下のファイルを置き、 CLI のオプションで指定

設定変更用ファイルとして、 CLI を実行するフォルダに `update.json` という名前で以下のファイルを配置します。

```update.json
{
  "com.example.HelloWorld": {
    "MERGE": {
    },
    "RESET": [
      ""
    ]
  }
}
```
※ `RESET` 配列に空文字列 (`""`) だけを入れることで、コンポーネントの設定を全体的にデフォルト値にリセットできる

参考ドキュメント: [コンポーネント設定の更新 - AWS IoT Greengrass](https://docs.aws.amazon.com/ja_jp/greengrass/v2/developerguide/update-component-configurations.html#reset-configuration-update)


そして、以下のように CLI コマンドを叩きます。最後の `--update-config` オプションが重要です。 ※recipeDir, artifactDir は環境に合わせて変更

```bash
sudo /greengrass/v2/bin/greengrass-cli deployment create  \
  --recipeDir ~/environment/GreengrassCore/recipes \
  --artifactDir ~/environment/GreengrassCore/artifacts \
  --update-config update.json
```

※ `--update-config` オプションは、JSON 文字列 or JSON ファイルを受け付けることができる

参考ドキュメント : [デプロイメント - AWS IoT Greengrass](https://docs.aws.amazon.com/ja_jp/greengrass/v2/developerguide/gg-cli-deployment.html)

## 詳細: 原因の確認

### 初回デプロイ

以下のような recipe.yaml をレシピとするコンポーネントをデプロイします。

```yaml: com.example.HelloWorld-1.0.0.yaml
RecipeFormatVersion: 2020-01-25
ComponentName: com.example.HelloWorld
ComponentVersion: 1.0.0
ComponentDescription: Example app
ComponentPublisher: Example company
ComponentConfiguration:
  DefaultConfiguration:
    Message: hoge
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      Run: 
        RequiresPrivilege: true
        Script: |
          python3 -u {artifacts:path}/hello_world.py '{configuration:/Message}'
```

これを `--update-config` オプションなしでデプロイすると、 `greengrass-cli component details` の結果は以下のようになります。

```text
$ sudo /greengrass/v2/bin/greengrass-cli component details --name com.example.HelloWorld
Component Name: com.example.HelloWorld
    Version: 1.0.0
    State: FINISHED
    Configuration: {"Message":"hoge"}
```

設定値は `{"Message":"hoge"}` です。この時点では、レシピの yaml に書いた通りの値です。

### 2回目のデプロイ: レシピの DefaultConfiguration 内の設定値のキーを変更してデプロイする

ここで、 `Message` だったキーを `Msg` に変更し、値も変更してみます。

```diff_yaml: com.example.HelloWorld-1.0.0.yaml
RecipeFormatVersion: 2020-01-25
ComponentName: com.example.HelloWorld
ComponentVersion: 1.0.0
ComponentDescription: Example app
ComponentPublisher: Example company
ComponentConfiguration:
  DefaultConfiguration:
-   Message: hoge
+   Msg: fuga
Manifests:
  - Platform:
      os: linux
    Lifecycle:
      Run: 
        RequiresPrivilege: true
        Script: |
          python3 -u {artifacts:path}/hello_world.py '{configuration:/Message}'
```

これを `--update-config` オプションなしでデプロイすると、 `greengrass-cli component details` の結果は以下のようになります。

```
Component Name: com.example.HelloWorld
    Version: 1.0.0
    State: FINISHED
    Configuration: {"Message":"hoge","Msg":"fuga"}
```

この通り、レシピの yaml からは削除した `{"Message":"hoge"}` が削除されることなく、変更後の `{"Msg":"fuga"}` がマージされてしまっています。

### Greengrass CLI の `--update-config` を使ってデプロイしてみる

今度は、Greengrass CLI を実行するフォルダに前述の `update.json` を置いて、以下のデプロイコマンドを叩いてみます。

```bash
sudo /greengrass/v2/bin/greengrass-cli deployment create  \
  --recipeDir ~/environment/GreengrassCore/recipes \
  --artifactDir ~/environment/GreengrassCore/artifacts \
  --update-config update.json
```

すると、 `greengrass-cli component details` の結果は以下のようになります。

```
Component Name: com.example.HelloWorld
    Version: 1.0.0
    State: FINISHED
    Configuration: {"Msg":"fuga"}
```

過去のデプロイで指定されていた値が一旦リセットされたうえで、レシピファイルに書かれた設定が反映されました。そのため、狙った通りの設定値にできています。

## おわりに

今回の例で指定していたのは雑な設定値のため影響がわかりづらいですが、私の開発では `accessControl` の削除・変更等を試行錯誤しているときに「設定が反映されないぞ……？」となり、実に大量の時間を溶かしてしまいました。 マメに CLI で設定値を確認すべきだった、というのも教訓です。

皆様が同じことで時間を溶かさないことを願っています。

## 余談

Greengrass コンポーネントの開発時には、レシピだけでなく様々なリソースを変更することになると思います。

IoT ポリシーに付与する権限の変更もその一つだと思いますが、こちらはキャッシュ機構により変更から反映まで 6-8 分ほどかかる場合があります。気長に待ちましょう。

参考ドキュメント: [AWS IoT Core ポリシー - AWS IoT Core](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-policies.html)