【问题标题】:use timestamp for null resource local exec对空资源本地执行使用时间戳
【发布时间】:2021-12-30 20:04:07
【问题描述】:

我只想每小时执行一次 exec 操作。意思是,如果现在是 12 点,那么在 13 点之前不要再次执行。

时间戳与 fomatdate 相结合将产生仅每小时不同的时间戳。

resource "null_resource" "helm_login" {
  triggers = {
    hour = formatdate("YYYYMMDDhh", timestamp())
  }
  provisioner "local-exec" {
    command = <<-EOF
      az acr login -n ${var.helm_chart_acr_fqdn} -t -o tsv --query accessToken \
        | helm registry login ${var.helm_chart_acr_fqdn} \
          -u "00000000-0000-0000-0000-000000000000" \
          --password-stdin
    EOF
  }

问题是 terraform 报告说这个值只有在 appy 之后才知道,并且总是想重新创建资源。

  # module.k8s.null_resource.helm_login must be replaced
-/+ resource "null_resource" "helm_login" {
      ~ id       = "4503742218368236410" -> (known after apply)
      ~ triggers = {
          - "hour" = "2021112010"
        } -> (known after apply) # forces replacement
    }

我观察到类似的问题,即从数据中获取值并在创建时传递给资源,这迫使我不使用这些数据值,而是对它们进行硬编码。

【问题讨论】:

  • 我猜这个问题出在trigger 上。做文档说The triggers argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.
  • "我只想每小时执行一次 exec 操作。"目前尚不清楚您的意思是什么,以及timestamp() 函数将如何帮助实现这一目标。请在问题中添加更多详细信息。
  • 如果时间戳没有改变,那么不要执行。这就是为什么它的格式只有在新的一小时才会有所不同。问题是 terraform 不会先对此进行评估,然后再确定触发值是否不同。
  • 这个确切的问题就是我在从数据中获取值时提到的问题。即使数据每次带来完全相同的值。 Terraform 想要重新创建某些资源,因为它说这只有在应用后才知道。它以这种方式工作有点愚蠢。如果你只能做一次,当你不想不断地重新创建资源时,从数据中获取它有什么意义。
  • 让我们澄清一下“每小时仅执行一次”terraform 不是调度程序,此代码可能会在 8:59 触发执行,然后在 9:01 再次触发...如果您需要它运行每小时你需要一些其他工具

标签: terraform


【解决方案1】:

正如您刚刚发现 terraform 在运行时评估时间戳功能,
这就是为什么我们看到: (known after apply) # forces replacement

但是我们可以为此做一些事情来实现您的目标,我们可以将小时作为参数传递:

variable "hour" {
  type = number
}

resource "null_resource" "test" {
  triggers = {
    hour = var.hour
  }
  provisioner "local-exec" {
    command = "echo 'test'"
  }
}

然后调用 terraform 我们这样做:
hour=$(date +%G%m%d%H); sudo terraform apply -var="hour=$hour"


第一次运行:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.test will be created
  + resource "null_resource" "test" {
      + id       = (known after apply)
      + triggers = {
          + "hour" = "2021112011"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

null_resource.test: Creating...
null_resource.test: Provisioning with 'local-exec'...
null_resource.test (local-exec): Executing: ["/bin/sh" "-c" "echo 'test'"]
null_resource.test (local-exec): test
null_resource.test: Creation complete after 0s [id=6793564729560967989]

第二次运行:

null_resource.test: Refreshing state... [id=6793564729560967989]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

【讨论】:

  • 老实说,这样做并不是很好。我自己已经有了这个想法,但认为它既丑陋又麻烦。我认为这是 terraforms 设计中的一个缺陷。在这种情况下,您可能会摆脱硬编码。但如前所述,当你从数据中获取这些东西时,它会变得非常烦人。尽管这不是我的问题。
  • 当然不是缺陷,这是预期的设计......硬编码肯定不会每小时触发任何事情......如果您对特定数据资源有问题,请打开一个新问题
  • 您在这里进行了相当多的硬编码。除了,您从外部注入硬编码值。它不是 terraform 边界内动态生成的值。如果一个值对 terraform 继续执行并重新创建资源的结果进行 2 次评估,您不认为这是有缺陷的吗?正是在那一刻,它没有做它所承诺的事情。 仅在值发生变化时触发。
  • 问题不在于特定的数据资源。它包含所有数据资源。一旦您将它们的值用作另一件事的输入,您就会得到与本示例完全相同的行为。 “只有申请后才知道”。
  • 如果它带来的价值在运行时是已知的,我们将看到同样的行为,同样适用于函数、资源或数据......这里对另一个问题的回答可能会有所启发,来自 Martin Atkins他是 terraform 项目的开发者之一:stackoverflow.com/a/67063790/7599833
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-08
  • 2018-07-28
  • 2015-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多