问题描述
我有一个 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 未与后端一起运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2