Разделить многострочный файл на переменную Terraform, чтобы получить доступ к значениям по их ключам - PullRequest
1 голос
/ 15 марта 2019

У меня есть сторонний поддерживаемый файл с большим количеством строк, и он выглядит так:

# 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 ]

2 голосов
/ 16 марта 2019

Часто лучше предварительно обрабатывать файлы, подобные этой, используя отдельную программу, написанную на языке программирования общего назначения, поскольку DSL Terraform не очень подходит для такой логики специального анализа.

В Terraform v0.11 и более ранних версиях отсутствуют примитивы, необходимые для реализации такого анализа в самом языке. Релиз v0.12.0 (который на момент написания в бета-версии ) вводит некоторые примитивы, которые 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"
}
0 голосов
/ 15 марта 2019

Имя файла 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: Для доступа к результирующим значениям вам необходимо использовать дополнительный ключ«.result» перед фактическим ключом «.output» из скрипта.

...