如何读取从terraform传递到powershell userdata脚本的Map类型的变量的值?

时间:2020-06-25 19:34:53

标签: powershell terraform terraform-provider-aws

我需要将terra类型的map变量从terraform传递到powershell userdata脚本,并能够在powershell脚本中访问映射的键值对。谢谢

userdata.tf

data "template_file" "user_data" {
  template = "${file("${path.module}/init.ps1")}"
  vars = {
    environment = var.env
    # I want to pass the values as shown below
    hostnames   = {"dev":"devhost","test":"testhost","prod":"prodhost"}
  }
}

init.ps1

$hostnames = "${hostnames}"
$environment = "${environment}"

if ($environment -eq "dev"){
   # print the value of the dev key in the hostname map here
}

2 个答案:

答案 0 :(得分:1)

不推荐使用template_file数据源。

注意:在Terraform 0.12和更高版本中,the templatefile function提供了一种内置机制,用于从文件渲染模板。除非使用的是Terraform 0.11或更早版本,否则请使用该函数。

首选templatefile function,这就是我的解决方案改用它的原因。

在任何一种情况下,模板var仅支持 map(string)。值必须是字符串。 JSON可以对任意树结构进行编码,包括将主机名映射为字符串。

在您的Terraform代码中,使用jsonencode主机名编码为JSON。

userdata.tf:

locals {
  user_data = templatefile("${path.module}/init.ps1" ,{
    environment = var.env
    # I want to pass the values as shown below
    hostnames   = jsonencode({"dev":"devhost","test":"testhost","prod":"prodhost"})
  })
}

在PowerShell中,使用the ConvertFrom-Json cmdlet从JSON解码主机名

init.ps1:

$hostnames = '${hostnames}' | ConvertFrom-Json
$environment = "${environment}"

if ($environment -eq "dev"){
   # print the value of the dev key in the hostname map here
}

更新:如注释中所述,-AsHashtable不一定会起作用,因为它是在PowerShell 6.0中添加的。 Windows 10和Windows Server 2016包含PowerShell 5.1。如果您的地图的键({"name" = "foo" ; "Name" = "bar"})仅区分大小写,则需要安装PowerShell 6.0或更高版本并使用ConvertFrom-Json -AsHashtable

答案 1 :(得分:1)

要在模板结果中包含集合值,您必须决定如何将其表示为字符串,因为模板结果始终是字符串。

PowerShell通过the ConvertFrom-Json cmdlet支持JSON编码,因此JSON字符串可能是一个不错的选择,尽管它带来了一些挑战,因为您必须确保将JSON字符串作为有效的PowerShell表达式写入结果中,这意味着我们还必须应用PowerShell转义。

将所有内容放在一起,您可以像这样调整模板:

$hostnames = '${replace(jsonencode(hostnames), "'", "''")}' | ConvertFrom-Json
$environment = '${replace(environment, "'", "''")}'

if ($environment -eq "dev"){
   Write-Output $hostnames["dev"]
}

jsonencode函数产生给定值的JSON编码版本。然后,上面的代码将结果传递给replace,这样结果中的任何'字符都将以''的形式转义,然后将整个结果放在单引号'中确保有效的PowerShell语法。

呈现模板的结果将是这样的:

$hostnames = '{"dev":"devhost","test":"testhost","prod":"prodhost"}' | ConvertFrom-Json -AsHashtable
$environment = 'dev'

if ($environment -eq "dev"){
   Write-Output $hostnames["dev"]
}

您似乎正在使用Terraform 0.12,因此应使用the templatefile function而不是template_file数据源。该功能更好,因为它可以接受任何类型的值,而数据源只能接受字符串值(因为它是为Terraform 0.11设计的)。

要使用templatefile,请找到您之前引用data.template_file.user_data的位置,并在其中使用templatefile函数:

templatefile("${path.module}/init.ps1", {
  environment = var.env
  hostnames   = {"dev":"devhost","test":"testhost","prod":"prodhost"}
})

然后您可以删除data "template_file" "user_data"块,因为此templatefile函数调用将替换它。