无法在Terraform的当前会话中设置环境变量。

huangapple go评论59阅读模式
英文:

Unable to set environment variable for current session in terraform

问题

我有一个通过terraform local-exec执行的操作,通过它我执行

```bash
export ABC=value

随后的模块内部有一个local-exec,从环境中读取值

echo $ABC > file.txt

当我执行时,会创建一个空的file.txt文件。位于模块中的第二个local-exec无法从terraform的apply会话中获取值

resource "null_resource" "export_environment_variable" {
  triggers = {
    always = timestamp()
  }
  provisioner "local-exec" {
    command = "export ABC=value"
  }
}

module "module_internal" {
   src = "./internal-module"
   depends_on = [null_resource.export_environment_variable]
}

/internal-module

resource "null_resource" "write-to-file" {
  triggers = {
    always = timestamp()
  }
  provisioner "local-exec" {
    command = "echo $ABC > file.txt"
  }
}

<details>
<summary>英文:</summary>

I have a terraform local-exec through which I execute 

```bash
export ABC=value

The subsequent module has a local-exec internally and reading the value from environment

echo $ABC &gt; file.txt

When i execute is an empty file.txt is created
The second local-exec which resides in the module is not able to fetch from the apply session in terraform

resource &quot;null_resource&quot; &quot;export_environment_variable&quot; {
  triggers = {
    always = timestamp()
  }
  provisioner &quot;local-exec&quot; {
    command = &quot;export ABC=value&quot;
  }
}

module &quot;module_internal {
   src = &quot;./internal-module&quot;
   depends_on = [null_resource.export_environment_variable]
}

/internal-module

resource &quot;null_resource&quot; &quot;write-to-file&quot; {
  triggers = {
    always = timestamp()
  }
  provisioner &quot;local-exec&quot; {
    command = &quot;echo $ABC &gt; file.txt&quot;
  }
}

答案1

得分: 1

当你使用 local-exec 如你所示的方式时,Terraform会启动你的shell作为子进程,并要求shell来评估脚本。在脚本评估完成后,shell进程结束,因此任何内存中的状态,如shell变量,都会丢失。

在你的示例中,你有两个独立的 local-exec provisioners,因此有两个完全独立的shell会话。你在这里所做的类似于如果你按照以下步骤进行操作:

  1. 在计算机上的一个窗口中打开终端。
  2. 在该终端中运行 export ABC=value
  3. 在计算机上的另一个独立窗口中打开另一个终端。
  4. 在该终端中运行 echo $ABC

就像Terraform中的两个独立的 local-exec provisioners一样,这两个终端都有各自独立的shell实例运行,因此不共享内存状态,如shell变量。

如果你想设置一个shell变量,然后以后再使用它,你需要在同一个shell进程中执行这两个操作,这意味着在同一个 local-exec provisioner 中执行这两个操作:

resource "null_resource" "export_environment_variable" {
  triggers = {
    always = timestamp()
  }
  provisioner "local-exec" {
    command = <<-EOT
      export ABC=value
      echo $ABC > file.txt
    EOT
  }
}

请注意,provisioners是最后的手段,可能有更好的方法来实现这个目标,而不需要使用local-exec。我在这里关注local-exec,因为这是你提出问题的内容,但这也许是一个XY问题的示例,如果你有兴趣探索替代解决方案,我建议提出一个新问题,描述你实际的问题,而不要假设provisioners涉及到解决方案。

英文:

When you use local-exec in the way you've shown, Terraform starts your shell as a child process and asks the shell to evaluate the script. After the script is evaluated, the shell process ends and so any in-memory state such as shell variables are lost.

In your example you have two separate local-exec provisioners and therefore two separate end entirely independent shell sessions. What you have done here is similar to what might happen if you followed the following steps:

  1. Open a terminal in a window on your computer.
  2. In that terminal, run export ABC=value.
  3. Open another separate terminal in a separate window on your computer.
  4. In that terminal, run echo $ABC.

Just as with the two separate local-exec provisioners in Terraform, these two terminals each have their own separate instance of your shell running and so do not share in-memory state such as shell variables.

If you want to set a shell variable and then use it later you will need to do both in the same shell process, which means doing both in the same local-exec provisioner:

resource &quot;null_resource&quot; &quot;export_environment_variable&quot; {
  triggers = {
    always = timestamp()
  }
  provisioner &quot;local-exec&quot; {
    command = &lt;&lt;-EOT
      export ABC=value
      echo $ABC &gt; file.txt
    EOT
  }
}

Note that provisioners are a last resort and there is probably a better way to achieve this goal that doesn't involve using local-exec at all. I've focused on local-exec here because that's what you asked the question about, but this is perhaps an example of XY Problem and if you're interested in exploring alternative solutions I would suggest starting a new question that describes the real problem you have without assuming that provisioners are involved in the solution.

huangapple
  • 本文由 发表于 2023年6月26日 17:20:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76555300.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定