Рубрики
Без рубрики

Работа с картами в шаблонах Terraform как JSON

В Terraform источник данных Template_file является предпочтительным методом, например, инъекцией … Tagged с помощью Terraform, Automation, ConfigManagement, Python.

В Терраформ , Template_file Источник данных является предпочтительным методом, например, ввода данных переменной в шаблон, как сценарий или файл конфигурации. В моем случае я высоко использую Template_file В рамках процедуры вращения для серверов на Equinix Metal который использует Cloud-init Чтобы запустить скрипт на первой загрузке для настройки хоста.

Для легкого и способности пользователя я использую карта Ресурс в Terraform для хранения всех URL-адресов для Kubernetes Manifests, которые я бы хотел применить к кластеру Kubernetes, как только Terraform создает хост, и Cloud-Init загрузил кластер, что выглядит так:

variable "workloads" {
  type = map

  default = {
    ceph_common = "https://raw.githubusercontent.com/rook/rook/release-1.0/cluster/examples/kubernetes/ceph/common.yaml"
    ceph_operator = "https://raw.githubusercontent.com/rook/rook/release-1.0/cluster/examples/kubernetes/ceph/operator.yaml"
    ceph_cluster_minimal = "https://raw.githubusercontent.com/rook/rook/release-1.0/cluster/examples/kubernetes/ceph/cluster-minimal.yaml"
    ceph_cluster =  "https://raw.githubusercontent.com/rook/rook/release-1.0/cluster/examples/kubernetes/ceph/cluster.yaml"
    open_ebs_operator = "https://openebs.github.io/charts/openebs-operator-1.2.0.yaml"
    tigera_operator = "https://docs.projectcalico.org/manifests/tigera-operator.yaml"
    calico = "https://docs.projectcalico.org/manifests/custom-resources.yaml"
    flannel = "https://raw.githubusercontent.com/coreos/flannel/2140ac876ef134e0ed5af15c65e414cf26827915/Documentation/kube-flannel.yml"
    metallb_namespace = "https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/namespace.yaml"
    metallb_release = "https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/metallb.yaml"
  }
}

Преимущество этого подхода, вместо того, чтобы жестко кодировать эти значения в Предурательница В Terraform (если вы не используете поставщика Kubernetes, которого я не являюсь), или в чем -то вроде сценария в облаке (т.е. T требуют изменения самого модуля Terraform, чтобы изменить манифестную версию, или для добавления или удаления рабочих нагрузок из вышеперечисленного- их можно изменить или переопределить (или полностью опущенные) из Terraform.tfvars Файл на машину пользователей. Это означает, что, если нагрузка изменяется, ресурс, в который он был встроен, может быть обновлен, а не переработан (уничтожен и повторный нанесен), в зависимости от того, как вы заканчиваете использование этой переменной, но это не так для этого примера. , потому что этот пример получен из кластерный предварительный завод Вместо того, чтобы производственная рабочая нагрузка терраформ.

Как правило, когда вы хотите потреблять переменную, в данном случае рабочие нагрузки , если бы это было типа строка , вы можете подключить это к таким шаблону:

data "template_file" "controller" {
  template = file("${path.module}/controller.tpl")

  vars = {
    workloads = var.workloads
  }
}

Однако, потому что рабочие нагрузки типа карта , он должен быть преобразован с помощью jsonencode :

...
  vars = {
    workloads = jsonencode(var.workloads)
  }
...

И тогда вы можете получить доступ к нему в своем файле шаблонов (в приведенном выше примере, который был controller.tpl :

#!/bin/bash

echo ${workloads}

Одна проблема, однако, я столкнулся, заключается в том, что это создает такой объект, как:

key1:value key2:value key3:value

и с тех пор, как я Действительно разыскиваюсь объект JSON, с которым я мог бы работать и проверить, я добавляю этот дополнительный шаг, чтобы преобразовать его, во -первых, в таблицу:

echo ${workloads} | sed 's| |\n|'g | awk '{sub(/:/," ")}1' | tee /root/workloads.data

Итак, данные теперь выглядят как:

key1 value
key2 value
key3 value

что обычно было бы достаточно легко поместить в ассоциативный массив, но мне понравилась идея использования Python для некоторой дополнительной проверки в какой -то момент в будущем, поэтому я также создал его копию этой таблицы в качестве файла JSON:

echo ${workloads} | sed 's| |\n|'g | awk '{sub(/:/," ")}1' | tee /root/workloads.data && \
cat << EOF > workloads.py
import json

filename = "/root/workloads.data"

with open(filename) as f:
    content = f.readlines()

workloads = {}

for w in content:
    key = w.split(" ")[0]
    value = w.split(" ")[1]
    workloads[key] = value.replace("\n","")

f = open("/root/workloads.json", "a")
f.write(json.dumps(workloads))
f.close()
EOF

python3 workloads.py

Поскольку, потенциально, я мог бы расширить сценарий для взаимодействия с API Kubernetes, чтобы применить рабочие нагрузки напрямую или любую другую автоматизацию, которую я мог бы добавить в будущем, но конечный результат здесь заключается в том, что у меня есть файл, который я могу разобрать:

{"key1": "value", "key2": "value", "key3":"value"}

В остальной части сценария, используя карту выше из Terraform:

cat workloads.json | jq .key1

Это может показаться излишним, и для наших целей здесь это абсолютно (как я уже отметил, как две дополнительные строки Bash могли бы создать ассоциативный массив из этих данных и все же быть иерным таким образом), но, надеюсь, он станет Немного яснее, что существует много подходов к обработке данных, управляемым Terraform в ресурсы, которые он не имеет видимости, в данном случае, когда ресурс, подобный серверу:

data "template_file" "controller" {
  template = file("${path.module}/controller.tpl")

  vars = {
    workloads = jsonencode(var.workloads)
  }
}

resource "metal_device" "web1" {
  project_id       = var.project_id
  hostname         = "web1"
  plan             = "c3.medium.x86"
  facilities       = ["ny5"]
  operating_system = "ubuntu_20_04"
  billing_cycle    = "hourly"
  user_data        = data.template_file.controller.rendered
}

подходит для обработки переменных данных в любом случае, когда вы хотели бы (CSV, возможно, таблица была в порядке для вас и т. Д.), Который в моем случае был больше JSON от объекта, который встретил эту схему.

Оригинал: “https://dev.to/jmarhee/working-with-maps-in-terraform-templates-as-json-2g36”