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

#terraform #hcl

#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)}"
  

Комментарии:

1. Вероятно, это связано local-exec с каким-то сценарием / манипуляцией.

2. Да, я пробую этот вариант прямо сейчас, и, похоже, это перспективный выбор.

Ответ №1:

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

В Terraform версии 0.11 и более ранних отсутствуют примитивы, необходимые для реализации подобного синтаксического анализа в самом языке. В версии v0.12.0 (которая на момент написания находится в бета-версии) представлены некоторые примитивы, которые действительно позволяют реализовать такого рода синтаксический анализ, хотя я все равно обычно предпочитаю делать это вне 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 amp;amp; 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.12. Я отмечаю это как решение, хотя я не могу протестировать его прямо сейчас. Но версия 0.12 — это большой шаг вперед для Terraform, и я надеюсь, что она скоро выйдет.

Ответ №2:

Имя файла — 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» из скрипта.

Комментарии:

1. эй, как мы можем получить список значений или список пар ключ-значение.. У меня есть {"privateIpAddress":"10.48.131.30"} {"privateIpAddress":"10.48.131.34"} это, и я хотел бы извлечь только ip-адреса и обработать их дальше..