Terraform null_resource 未与后端一起运行 [英] Terraform null_resource not running with backend

查看:25
本文介绍了Terraform null_resource 未与后端一起运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 terraform 对象的变量映射,如下所示

I have a terraform variable map of objects as given below

variable "MyProj" {
  type = map(object({
  name     = string
  type     = string
 }))
default = {
  "Proj1" = {
      name      = "Proj1"
      programme = "java"
   },
   "Proj2" = {
      name       = "Proj2"
      programme  = "npm"
  }
 }
}

我还有一个空资源代码,只要根据上面的 map(objects()) 和所需状态识别出更改,它就会运行一个批处理脚本.

I also have a null resource code that will run a batch script whenever change is identified based on the above map(objects()) and desired state.

   resource "null_resource" "nullr" {
   for_each = var.MyProj

   provisioner "local-exec" {
   command = "bash /home/myscript.sh ${each.value.name} ${each.value.progrmme}
  }
}

我的意图是,只要在上面的 map() 中识别出更改,则应该运行 null 资源.

My intention is that whenever a change is identified in the above map() then the null resource should run.

当我在本地机器中保持 terraform 状态时,这会按预期运行.但是,当我使用 azurem 后端将 terraform 状态保存在 Azure blob 容器中时,它并没有运行 null_resource.即使我将后端用于 terraform 状态,我应该在配置中做哪些更改

This is running as expected when I keep the terraform state in my local machine. But when I keep the terraform state in a Azure blob container using azurem backend it is not running the null_resource. What change I should do in the configuration even if I use a backend for terraform state

推荐答案

我想从这里开始,似乎你在这里所做的可能超出了 Terraform 的典型范围:通常是工具像 npm 属于build";构建/部署管道的步骤,而 Terraform 并不是真正打算或设计用于处理该系列的用例.由于它是一种通用的可编程工具,如果您有创意,您当然可以让它做超出其范围的事情,但它通常带有警告和限制.

I want to start here by saying that it seems like what you are doing here might be outside of Terraform's typical scope: usually tools like npm belong to the "build" step of a build/deploy pipeline, and Terraform isn't really intended or designed to deal with that family of use-cases. Since it's a general programmable tool you can of course make it do things outside of its scope if you are creative, but it usually comes with caveats and limitations.

我将尝试在您编写问题时回答您的问题,但我还建议您更哲学地思考是否最好使用在 Terraform 之前运行的单独进程来解决打算解决的任何问题一个管道,或者如果整个问题可以通过明确设计用于支持构建和部署流程的其他系统来更好地解决.

I'm going to attempt to answer your question as you wrote it but I'd also suggest thinking more philosophically about whether it would be better to solve whatever problem this is intended to solve using a separate process that runs before Terraform in a pipeline, or if perhaps the entire problem would be better solved by some other system that's explicitly designed to support build and deploy processes.

null_resource 资源类型是一种特殊的逃生舱".在 Terraform 中,它故意不做任何事情,以便您可以将不自然地属于资源的配置器附加到它.供应商的预期目的(尽管 作为最后的手段)是实现特定对象需要执行的额外步骤才能完全运行,例如将一些需要的数据写入虚拟机的文件系统.

The null_resource resource type is a special "escape hatch" in Terraform that intentionally does nothing so that you can attach provisioners to it that wouldn't otherwise naturally belong to a resource. The intended purpose of provisioners (although as a last resort) is to implement additional steps that a particular object needs carried out in order to become fully operational, such as writing some needed data into a virtual machine's filesystem.

普通资源类型具有由远程系统定义的关于可以就地应用哪些类型的更改以及哪些类型的更改需要重新创建对象的固有规则.因为 null_resource 不代表特定的远程对象类型,所以它没有任何这样的 inherent 规则,但它确实有一个更人为的 triggers 参数除了在对象的值与上一次运行不同时强制替换对象之外什么都不做.

Normal resource types have inherent rules defined by the remote system about what sorts of changes can be applied in-place and what sorts of changes require re-creating the object. Because null_resource represents no particular remote object type, it doesn't have any such inherent rules, but it does have the more artificial concept of a triggers argument that does nothing except force replacing the object whenever its value differs from the previous run.

为了强制替换您的 null_resource 并因此强制其关联的配置程序重新运行,则需要使用通常保持不变的值填充 triggers 参数未更改,但如果更改,应该会导致配置程序重新运行.

In order to force your null_resource to be replaced and therefore to force its associated provisioners to re-run then will require populating the triggers argument with values that will normally stay unchanged but that should, if changed, cause the provisioner to re-run.

在您的情况下,您的 var.MyProj 中的值似乎可以用作触发器,但因为 triggers 是我们的字符串映射d 需要先将其编码为字符串.在这种情况下,JSON 编码可能是一个合理的答案:

In your case it seems like the values within your var.MyProj might be a reasonable thing to use as triggers, though because triggers is a map of strings we'd need to encode it to a string first. JSON encoding could be a reasonable answer in that case:

resource "null_resource" "nullr" {
  for_each = var.MyProj

  triggers = {
    settings = jsonencode(each.value)
  }

  provisioner "local-exec" {
    command = "bash /home/myscript.sh ${each.value.name} ${each.value.progrmme}
  }
}

因为每个资源实例的triggers只引用当前的each.value,在var.MyProj中增加了一个新的入口不应影响资源的任何现有实例,因此不会重新运行任何供应商.但是,如果您编辑现有密钥之一,那么它将使用新设置重新运行.

Because the triggers for each instance of the resource only refers to the current each.value, adding a new entry to var.MyProj should not affect any of the existing instances of the resource, and thus not re-run any provisioners. However, if you edit one of the existing keys then it will re-run with the new settings.

如果您预计需要重新运行特定资源的配置程序,即使它的名称或progrmme"都没有.已更改,那么您可能希望将第三个属性添加到 var.MyProj 的元素类型,它是一个整数或一些特殊的字符串标识符,您每次需要重新运行时都会更改它.然后,您可以更改该属性的值以强制它重新运行,即使它将重新运行与以前相同的程序.

If you expect to need to re-run a particular resource's provisioner even though neither its name or "progrmme" have changed then you may wish to add a third attribute to the element type of var.MyProj which is an integer or some special string identifier that you'll change each time it needs to re-run. You could then change the value of that attribute to force it to re-run even though it'll be re-running the same program as before.

要考虑的另一种情况是,如果此 myscript.sh 的内容发生更改,会发生什么情况.如果您想在每次脚本更改时重新运行脚本,那么您可以添加另一个 triggers 条目来捕获文件的校验和,因此每次文件更改时都会更改:

Another situation to consider is what should happen if the content of this myscript.sh changes. If you want to re-run the script each time it changes then you can add another triggers entry to capture a checksum of the file, which will therefore change each time the file changes:

resource "null_resource" "nullr" {
  for_each = var.MyProj

  triggers = {
    settings        = jsonencode(each.value)
    script_checksum = filesha256("/home/myscript.sh")
  }

  provisioner "local-exec" {
    command = "bash /home/myscript.sh ${each.value.name} ${each.value.progrmme}
  }
}

这篇关于Terraform null_resource 未与后端一起运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆