はじめに
AWS Cloudwatch Synthetics CanaryをTerraformで構築する機会があったのでハマった箇所、工夫した箇所を記載していく。
ハマった箇所(source codeの配置場所)
Scriptをzip化して、CanaryにUPしているのだが、Canaryは作成できたが以下エラーが出力され処理に失敗していた。
2023-10-17T11:00:21.387Z ERROR: Canary error:
Error: Cannot find module '/opt/nodejs/node_modules/pageLoadBlueprint'Require stack:- /var/task/index.js
- /var/runtime/index.mjs Stack: Error: Cannot find module '/opt/nodejs/node_modules/pageLoadBlueprint'Require stack:
- /var/task/index.js
- /var/runtime/index.mjs at Module._resolveFilename
(node:internal/modules/cjs/loader:1077:15) at Module._load
(node:internal/modules/cjs/loader:922:27) at Module.require
(node:internal/modules/cjs/loader:1143:19) at require
(node:internal/modules/cjs/helpers:121:18) at exports.handler
(/var/task/index.js:85:30) at process.processTicksAndRejections
(node:internal/process/task_queues:95:5)
原因
ソースコードを格納するディレクトリがNGだった。
処理が失敗していたときはcanary_script/source/pageLoadBlueprint.js"
に配置していた。
canary_script/source/nodejs/node_modules/pageLoadBlueprint.js"
に変えたところうまく処理が行えるようになった。
つまりsource codeの置き場所としてはnodejs/node_modules/
の配下でないとNG。
zip化するときの処理は以下でおこなっている。
data "archive_file" "canary_zip" {
type = "zip"
source_dir = "${path.module}/canary_script/source"
output_path = "${path.module}/canary_script/synthetics.zip"
}
フォルダ構成
.
├── canary_script
│ └── source
│ └── pageLoadBlueprint.js
├── cloud_watch_alarm.tf
├── cloud_watch_canary.tf
├── cloud_watch_canary_iam.tf
├── cloud_watch_canary_s3.tf
├── cloud_watch_log.tf
├── event_bridge.tf
├── sns.tf
└── variables.tf
.
├── canary_script
│ └── source
│ └── nodejs
│ └── node_modules
│ └── pageLoadBlueprint.js
├── cloud_watch_alarm.tf
├── cloud_watch_canary.tf
├── cloud_watch_canary_iam.tf
├── cloud_watch_canary_s3.tf
├── cloud_watch_log.tf
├── event_bridge.tf
├── sns.tf
└── variables.tf
工夫した箇所(source codeを修正したらcanaryを更新させる)
動いたは良いものの、今度はsource code内で記述が誤っていた箇所があったのでsource codeを修正してterraform plan
を実行したところ、no change
となってしまい、変更が検知されなかった。
原因
zip化の処理を行っているが、zip後のファイルが同じ名前であった為、terraform plan
を実行しても変更差分として検出されなかった。
先に完成系のコード
対処
zip化した後のファイル名にhash値を入れることにより、検知させるようにする。
# source code zip
data "local_file" "canary_source" {
filename = "${path.module}/canary_script/source/nodejs/node_modules/pageLoadBlueprint.js"
}
locals {
source_hash = sha256(data.local_file.canary_source.content)
}
data "archive_file" "canary_zip" {
type = "zip"
source_dir = "${path.module}/canary_script/source"
output_path = "${path.module}/canary_script/synthetics_${local.source_hash}.zip"
}
# canary
resource "aws_synthetics_canary" "synthetics" {
name = "${var.name}-${var.env}-https"
start_canary = var.start_canary
artifact_s3_location = "s3://${aws_s3_bucket.synthetics.bucket}/logs/"
execution_role_arn = aws_iam_role.synthetics.arn
handler = "pageLoadBlueprint.handler"
zip_file = data.archive_file.canary_zip.output_path
runtime_version = "syn-nodejs-puppeteer-6.0"
schedule {
expression = "rate(5 minutes)"
}
run_config {
timeout_in_seconds = 60
}
lifecycle {
create_before_destroy = true
}
}
コード解説
- まずはsource codeを指定する。
data "local_file" "canary_source" {
filename = "${path.module}/canary_script/source/nodejs/node_modules/pageLoadBlueprint.js"
}
- 次にsource codeのハッシュ値を取得する。
locals {
source_hash = sha256(data.local_file.canary_source.content)
}
- ハッシュ値を取得したら、zip化後のファイル名にhash値を入れるようにする。
data "archive_file" "canary_zip" {
type = "zip"
source_dir = "${path.module}/canary_script/source"
output_path = "${path.module}/canary_script/synthetics_${local.source_hash}.zip"
}
- 最後にcanaryの
zip_file
でzip化した後のファイル名を引っ張ってくるようにする。
# canary
resource "aws_synthetics_canary" "synthetics" {
name = "${var.name}-${var.env}-https"
start_canary = var.start_canary
artifact_s3_location = "s3://${aws_s3_bucket.synthetics.bucket}/logs/"
execution_role_arn = aws_iam_role.synthetics.arn
handler = "pageLoadBlueprint.handler"
zip_file = data.archive_file.canary_zip.output_path
runtime_version = "syn-nodejs-puppeteer-6.0"
schedule {
expression = "rate(5 minutes)"
}
run_config {
timeout_in_seconds = 60
}
lifecycle {
create_before_destroy = true
}
}
これでsource codeに変更があった場合はhash値も変わるので変更差分として検出できるようになる。