zxでTerraformのファイルにlifecycle prevent_destroyを一括で付与する

概要

Terraformの任意のリソースにprevent_destory = trueを付与したい。
zxでスクリプトを書いたので記録。

  • 挙動
    lifecycleブロックがなければ追記してprevent_destory = trueをセット。
    lifecycleブロックがある場合は、falseのものもtrueにする。

環境

zx --version                                             
7.1.1

スクリプト

#!/usr/bin/env zx
// eg. zx scripts/addPreventDestroy.mjs --dir path/to/resource --resource aws_s3_bucket
const { resource, dir } = argv;
$.verbose = true

async function hasLifeCycle(file, block) {
  const res = await $`cat ${file} | hcledit block get ${block}.lifecycle`
  if (res.stdout === "") return false
  return true
}

async function hasPreventDestroy(file, block) {
  const res = await $`cat ${file} | hcledit attribute get ${block}.lifecycle.prevent_destroy`
  if (res.stdout === "") return false
  return true
}

async function appendLifeCycleWithPreventDestory(file, block) {
  await $`cat ${file} | hcledit block -f ${file} -u append ${block} lifecycle --newline`
  await $`cat ${file} | hcledit attribute -f ${file} -u append ${block}.lifecycle.prevent_destroy true`
}

async function setPreventDestroy(file, block) {
  await $`cat ${file} | hcledit attribute -f ${file} -u set ${block}.lifecycle.prevent_destroy 'true'`
}

async function appendPreventDestroy(file, block) {
  await $`cat ${file} | hcledit attribute -f ${file} -u append ${block}.lifecycle.prevent_destroy 'true'`
}

function isCommentOut(blocks) {
  return (blocks.length === 1 && blocks[0] === "")
}

async function listFliles() {
  const files = (await $`grep -l -r --exclude-dir .terraform "resource \\"${resource}\\"" ${dir}  || true `).stdout.trim().split('\n')
  return files.filter((v) => v)
}

async function addPreventDestroy(resource) {
  const files = listFliles()
  for await (const file of files) {
    const res = (await $`cat ${file} | hcledit block list | grep "resource.${resource}\\." || true `)
    const blocks = res.stdout.trim().split('\n')
    if (isCommentOut(blocks)) continue
    for await (const block of blocks) {
      const ifHasLifleCycle = await hasLifeCycle(file, block)
      if (ifHasLifleCycle) {
        const ifHasPreventDestroy = await hasPreventDestroy(file, block)
        if (ifHasPreventDestroy) {
          await setPreventDestroy(file, block)
        } else {
          await appendPreventDestroy(file, block)
        }
      } else {
        await appendLifeCycleWithPreventDestory(file, block)
      }
    }
  }
}

await addPreventDestroy(resource)

実行方法

zx scripts/addPreventDestroy.mjs --dir path/to/resource --resource aws_s3_bucket

これでpath/to/resource配下のすべてのaws_s3_bucketprevent_destory=trueを付与する。

参考

https://github.com/google/zx

https://developer.hashicorp.com/terraform/tutorials/state/resource-lifecycle#prevent-resource-deletion

https://github.com/minamijoyo/hcledit