Может ли Terraform отслеживать каталог на предмет изменений? - PullRequest
0 голосов
/ 02 июля 2018

Я хочу отслеживать каталог файлов и, если один из них изменяется, повторно загружать и запускать некоторые другие задачи. Мое предыдущее решение включало мониторинг отдельных файлов, но это подвержено ошибкам, так как некоторые файлы могут быть забыты:

resource "null_resource" "deploy_files" {    
  triggers = {
    file1 = "${sha1(file("my-dir/file1"))}"
    file2 = "${sha1(file("my-dir/file2"))}"
    file3 = "${sha1(file("my-dir/file3"))}"
    # have I forgotten one?
  }

  # Copy files then run a remote script.
  provisioner "file" { ... }
  provisioner "remote-exec: { ... }
}

Мое следующее решение - взять хеш структуры каталогов в одном ресурсе и использовать этот хеш в качестве триггера во втором:

resource "null_resource" "watch_dir" {
  triggers = {
    always = "${uuid()}"
  }

  provisioner "local-exec" {
    command = "find my-dir  -type f -print0 | xargs -0 sha1sum | sha1sum > mydir-checksum"
  }
}


resource "null_resource" "deploy_files" {    
  triggers = {
    file1 = "${sha1(file("mydir-checksum"))}"
  }

  # Copy files then run a remote script.
  provisioner "file" { ... }
  provisioner "remote-exec: { ... }
}

Это работает нормально, за исключением того, что изменения в mydir-checksum принимаются только после первого apply. Так что мне нужно apply дважды, что не здорово. Это что-то вроде клуджа.

Я не вижу более очевидного способа отслеживания изменений в содержимом всего каталога. Есть ли стандартный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 13 июля 2018

У меня тоже было такое же требование, я реализовал его ниже, используя data.external ресурс:

  • Написал скрипт, который выдаст мне контрольную сумму каталога, используя md5sum

    #!/bin/bash
    #
    # This script calculates the MD5 checksum on a directory
    #
    
    # Exit if any of the intermediate steps fail
    set -e
    
    # Extract "DIRECTORY" argument from the input into
    # DIRECTORY shell variables.
    # jq will ensure that the values are properly quoted
    # and escaped for consumption by the shell.
    eval "$(jq -r '@sh "DIRECTORY=\(.directory)"')"
    
    # Placeholder for whatever data-fetching logic your script implements
    CHECKSUM=`find ${DIRECTORY} -type f | LC_ALL=C sort | xargs shasum -a 256 | awk '{ n=split ($2, tokens, /\//); print $1 " " tokens[n]} ' |  shasum -a 256 | awk '{ print $1 }'`
    
    # Safely produce a JSON object containing the result value.
    # jq will ensure that the value is properly quoted
    # and escaped to produce a valid JSON string.
    jq -n --arg checksum "$CHECKSUM" '{"checksum":$checksum}'
    
  • Создано data.external как показано ниже

    data "external" "trigger" {
      program = ["${path.module}/dirhash.sh"]
    
      query {
        directory = "${path.module}/<YOUR_DIR_PATH_TO_WATCH>"
      }
    }
    
  • Использовать указанный выше ресурс results в качестве триггера для null_resource

    resource "null_resource" "deploy_files" {
      # Changes to any configuration file, requires the re-provisioning
      triggers {
        md5 = "${data.external.trigger.result["checksum"]}"
      }
      ...
    }
    

PS: скрипт зависит от jq

Обновление: Обновлена ​​логика вычисления контрольной суммы, чтобы нейтрализовать эффект поиска на разных платформах.

0 голосов
/ 21 февраля 2019

Вы можете использовать "archive_file" источник данных :

data "archive_file" "init" {
  type        = "zip"
  source_dir = "data/"
  output_path = "data.zip"
}

resource "null_resource" "provision-builder" {
  triggers = {
    src_hash = "${data.archive_file.init.output_sha}"
  }

  provisioner "local-exec" {
    command = "echo Touché"
  }
}

Пустой ресурс будет повторно предоставлен, если и только если хэш архива изменился. Во время обновления архив будет перестраиваться всякий раз, когда изменяется содержимое source_dir (в этом примере data/).

0 голосов
/ 03 июля 2018

Не похоже, что Terraform предоставляет какую-либо функцию обхода дерева каталогов, поэтому единственное решение, о котором я могу подумать, - это использовать какой-то внешний инструмент для этого, например, Make:

all: tf.plan

tf.plan: hash *.tf
        terraform plan -o $@

hash: some/dir
        find $^ -type f -exec sha1sum {} + > $@

.PHONY: all hash

и затем в вашем файле Terraform:

resource "null_resource" "deploy_files" {    
  triggers = {
    file1 = "${file("hash")}"
  }

  # Copy files then run a remote script.
  provisioner "file" { ... }
  provisioner "remote-exec: { ... }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...