terraformでファイルのハッシュを確認するメモ(ついでにnull_resourceについて)

概要

  • terraformのLambda layer等を作成するときに、ファイル更新を検知したい

詳細

archive_file

よくある手法が、Data sourceであるarchive_fileを利用する方法

registry.terraform.io

data "archive_file" "main" {
  type        = "zip"
  source_dir  = "${path.module}/${var.dir_name}/hogehoge"
  output_path = "${path.module}/${var.dir_name}/fuga/layer.zip"
}

このように、zipファイルを特定のディレクトリをもとに作ってくれる機能。

resource "aws_lambda_layer_version" "lambda_layer" {
  layer_name       = "layer-name"
  filename         = data.archive_file.main.output_path
  source_code_hash = data.archive_file.main.output_base64sha256

  skip_destroy = false
}

このようにdata.archive_file.main.output_base64sha256といった感じでZipのbase64sha256が取得でき、Zipファイルの変更を検知してくれる

直接ファイルのsha256を参照する

filebase64sha256を利用する

archive_fileを使わずに、直接sha256を参照することも可能。
あまりないかもしれないが、ローカルの特定のパスにZipファイルが存在することがわかっている場合等に有効と思われる

filebase64sha256("/path/to/file")
resource "aws_lambda_layer_version" "lambda_layer" {
  layer_name       = "layer-name"
  filename         = data.archive_file.main.output_path
  source_code_hash = filebase64sha256("/path/to/file")

  skip_destroy = false
}

このように、直接ファイルのbase64sha256を取得可能

ちなみに、base64sha256という関数もあり、これは引数に渡された文字列のbase64sha256を取るということっぽいので間違えないように。
これのせいで結構ハマった。

Lambda layerに限ったメモ

Lambda layerを前述のようなZipファイルから作成するのは定番の手法と思われるが、
10MB以上のファイルになるとエラーが出てしまうことがある。

S3を利用してのアップロードを検討する必要がある

クラスメソッドさんの記事でも紹介されている

dev.classmethod.jp

null_resourceを利用してZipを作ってそれをs3にコピーする技

resource "null_resource" "copy_to_s3" {
  triggers = {
    "code_diff" = join("",
      [
        filebase64("/path/to/my-source"),
        filebase64("/path/to/build-lambda.sh"),
      ]
    )
  }

  provisioner "local-exec" {
    command = "/bin/bash /path/to/build-lambda.sh"
  }

  provisioner "local-exec" {
    command = "aws s3 cp /path/to/outputs/layer.zip s3://${var.bucket_path}"
  }
}

このように、特定のファイルに変更が入ったことを検知して任意のコマンドを実行することが可能

上記の例だと、 "/path/to/my-source", "/path/to/build-lambda.sh"に変更がないことをnull_resourceが確認し、変更があったときにlocal-execで指定されたコマンドを実行することとなる

"/bin/bash /path/to/build-lambda.sh"で何かしらのZipファイルを作って、
作成したZipファイルを"aws s3 cp /path/to/outputs/layer.zip s3://${var.bucket_path}"でS3のバケットにコピーするようなイメージ