将多行文件拆分为Terraform变量,以通过键访问值

时间:2019-03-15 11:38:59

标签: terraform hcl

我有一个第三方维护的文件,其中包含很多行,看起来像:

# a comment lines
aaa.bbb.cc 423 
ddd.ee.fff 452
...
tons.like.them 111

是否可以使用以下语法将文件加载到本地地图并在Terraform中访问其键?

"${lookup(var.locals.mylist, 'ddd.ee.fff', 0)}"

2 个答案:

答案 0 :(得分:2)

通常最好使用通用编程语言编写的单独程序对此类文件进行预处理,因为Terraform的DSL不适合这种即席解析逻辑。

Terraform v0.11和更早的版本缺少在语言本身中实现这样的解析所需的原语。 v0.12.0版本(在撰写本文时为in beta)引入了一些 do 允许实现这种解析的原语,尽管我通常仍然更喜欢在外部进行尽可能将Terraform作为预处理步骤。

话虽如此,这是一个使用Terraform v0.12功能将类似于您的示例的文件解析为地图的示例:

locals {
  raw_lines = [
    for line in split("\n", file("${path.module}/input.txt")) :
    split(" ", trimspace(line))
  ]
  lines = [
    for line in local.raw_lines :
    line if length(line[0]) > 0 && substr(line[0], 0, 1) != "#"
  ]
  records = { for line in local.lines : line[0] => line[1] }
}

output "result" {
  value = local.records
}

给出以下输入文件:

# a comment line
aaa.bbb.cc 423 
ddd.ee.fff 452
tons.like.them 111

# another comment
another.record abc

这会使用Terraform v0.12.0-beta1产生以下结果:

$ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

result = {
  "aaa.bbb.cc" = "423"
  "another.record" = "abc"
  "ddd.ee.fff" = "452"
  "tons.like.them" = "111"
}

答案 1 :(得分:0)

文件名为myfile.txt,内容为:

# a comment line
aaa.bbb.cc 423 
ddd.ee.fff 452
...
tons.like.them 111

数据查询应类似于:

data "external" "myfile" {
  program = [
    "bash",
    "${path.module}/template/parser.sh",
    "${path.module}/template/myfile.txt",
    "ddd.ee.fff"
  ]
}

template/parser.sh包含:

#!/usr/bin/env bash
set -eo pipefail

CONFIG=$(cat $1|grep -v '#' | sed 's/ /=/g' | jq -R -n -c '.data = ([inputs|split("=")|{(.[0]):.[1]}] |add)')

OUTPUT=$(echo $CONFIG | jq -r '.data["'$2'"]')
jq -n --arg output "$OUTPUT" '{"output":$output}'

这个棘手的脚本将返回:

{"output": 452}

然后可以使用插值来获得结果值:

${data.external.myfile.result.output}

不幸的是,我没有找到如何将完整的行列表加载到Terraform并使用“变量变量”或lookup()访问它们的方法。如果bash脚本返回第一个jq调用的结果,则Terraform会引发异常:

command "bash" produced invalid JSON: json: cannot unmarshal object into Go value of type string

Update2::要访问结果值,需要在脚本中的实际“ .output”键之前使用附加键“ .result”。