首页 > 解决方案 > Terraform Plan 为 Windows 上的列表变量传递值

问题描述

在以下 YAML 脚本中,我想将 IP 作为 terraform 变量中的列表传递。该变量已在 Terraform 代码中定义为 List。范围是在Windows 代理上的 Azure DevOps 管道内运行此 CLI 。运行管道时,它失败并显示以下消息:意味着 -var='ips=$(ips)'未正确传递。我也试过了-var="ips=$(ips)"。我试图分配的值是["123.456.111","123.456.222"] 如何在这种情况下正确地将参数作为列表传递的文本?

我在下面附上了使用 Terraform 中变量 ips 的代码。

在此处输入图像描述

 - task: CmdLine@2
            displayName: Terraform Plan
            inputs:
              script: terraform plan -input=false -out=tfplan -var='ips=$(ips)'
              workingDirectory: infrastructure/terraform/dev
locals {
   }
  ips           = tolist(toset(var.ips))
  feature_flags = {
    provision_vm      = tobool(var.provision_vm)
    provision_webapp  = tobool(var.provision_webapp)
  }
}

标签: azureazure-devopsyamlterraform

解决方案


在运行诸如 Terraform 之类的命令行工具时,重要的是要了解您的命令在到达最终运行的命令的过程中将通过哪些命令行解释器和其他层。

在像 Linux 或 Mac OS X 这样的 Unix 系统上,你的命令行通常会被 shell 解释,比如bashor zsh。Unix 风格的 shell 遵循这样的约定,即'字符标记要完全按字面解释的字符序列,因此使用-var='foo=bar baz'shell 之类的命令行子字符串来处理这些字符',在此过程中将其删除,从而将最终参数发送到程序是-var=foo=bar baz,这恰好是 Terraform 对此参数期望的语法,因此它可以工作。

不幸的是,在 Windows 上,约定是相当不同的。您的命令行可能由 Windows 命令解释器 ( cmd.exe) 或其他一些解释器(如 PowerShell)处理。每个都有自己的处理命令行的约定,这意味着可以根据您使用的解释器对相同的命令行进行不同的解释。

对于运行 Terraform,我建议确保您尽可能使用 Windows 命令解释器,因为它的命令行处理规则相对简单:它根本不解释引号,只是将完整的命令行参数作为单个字符串。但是,这确实意味着在 Windows 上,类似这样的命令行将-var='foo=bar baz'传递给 Terraform,其编写方式与此完全相同'引号仍然存在,因此命令行解析将失败。

"Windows 上的Terraform遵循用 C 编写的软件或使用解析命令行的 Windows API 函数使用的典型命令行解析约定,其中一部分约定是使用当使用 Windows 命令解释器在 Windows 上运行 Terraform 时,您需要将字符的文字序列括起来",然后用反斜杠转义任何文字字符,如下所示: "

-var="ips=[\"123.456.111\",\"123.456.222\"]"

由于您打算从自动化工具中的变量填充它,因此只有在该自动化工具具有自动转义带反斜杠的引号的模式时,这才有效,否则结果将无效。

像这样在模板化命令行上处理所有不同的解析层可能会非常混乱,因此将变量值放在文件.tfvars然后在命令行上传递文件名通常更容易。在这种情况下,Terraform 将直接解析该文件的内容,而不会受到命令行解释器的任何干扰,因此您只需要处理 Terraform 自己的语言,而不是顶部的额外分层 shell 语言。


推荐阅读