В Терраформ , 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”