概要
基本的にタイトルの通りです。
AWS IoT ルールアクションをCDKで作成したところ、利用していたCDKバージョンでデフォルト値となっていたSQL ステートメントのバージョンが(執筆時2024.11.30現在)推奨となっている 2016-03-23
ではなく 2015-10-08
となっていたことで、ルールがうまく動かず、解決に時間を要したという話です。
環境
- CDK:
2.163.1
(2024.10.23 リリース)
つまづいた背景・原因
いくつかありますが、大きなものは以下です。
- CDKで作成する前に手動でIoT ルール・SQLステートメントを作成し、動作確認をしていた
手動で作成した場合、デフォルトでは 2016-03-23
が選ばれております。また他の選択肢を見ても、 Recommended
が入っているため、普通に作れば古いバージョンを選ばないと思います。
そもそもCDKで作るならなぜ手動でも作るんだ?というツッコミもあるかと思います。いろんな事情がありますが、SQLステートメントの記述修正でデプロイを繰り返したくないこと・デバイス側からのデータI/Fの延長線上にある処理であることなどから、とりあえず疎通を先に試す、という背景が主な理由です。
- CDKでIoT ルールを定義する際に、バージョンまで意識していなかった
他のバージョンの状態を把握しているわけではありませんが、少なくとも今回利用していたCDKバージョンでは、IoT ルール作成時にSQLバージョンの指定が必須ではありませんでした。つまり「CDK側でよしなにしてくれる」範疇になっていたので、まさか現在推奨されているバージョンではないものがデフォルトとして設定されているとは思いもよりませんでした。
また、今までSQLバージョン間の差異についても特別意識したことがなかったです。
問題のSQLステートメント
引っかかったのは以下の部分でした。
SELECT parse_time("yyyy-MM-dd'T'HH:mm:ss'Z'", timestamp) as registered_time FROM "#"
公式のリファレンス引用:
parse_time 機能を使用して、タイムスタンプを人間が判読可能な日付/時刻形式にフォーマットします。SQL バージョン 2016-03-23 以降でサポートされています。 タイムスタンプ文字列をミリ秒に変換するには、「time_to_epoch(String, String)」を参照してください。
実際のエラーは以下の通りです。
上記で作成しようとしていたキー(registered_time)はテーブルのソートキーに当たるものでした。
ルール: dynamoDBv2
エラー:
DynamoDBv2 Put record failed. The error received was One or more parameter values were invalid: Missing the key registered_time in the item (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; (以下略)
SQLバージョン 2016-03-23
では動くのに、 2015-10-08
では動かなかったのはこのせいでした。
上記 parse_time
関数はIoT Coreでのデータ受信時刻を後続処理で活用するのに不可欠な関数かと思っていますが、旧バージョンにはなかったということですね。
問題のCDK
該当の問題のIoTルール作成時の引数に関する公式のリファレンスの引用:
AwsIotSqlVersion
The version of the SQL rules engine to use when evaluating the rule.
The default value is 2015-10-08.
Required: No
Type: String
2015-10-08
がデフォルトの設定値です、とはっきり書いてありますね。
Githubでfeature-request出そうかめちゃくちゃ迷いました。
最後に
リソースに何らかのバージョン指定があれば、デフォルト設定しているのかもっと気をつけなければいけないですね。
(そういえば、CDKがらみでバージョンにまつわる記事を過去にも書いていました... )