Terraform — создание и передача файлов между модулями в цикле

# #terraform #terraform-modules #terraform-provider-kubernetes #terraform-provider-gitlab

Вопрос:

Мои сценарии TF создают ресурсы k8s и генерируют файлы kubeconfig на основе template_file .
Которые я затем хочу передать другому модулю (который использует поставщика GitLab — чтобы сохранить их как переменные GitLab).

До сих пор я создавал только один kubconfig, и подход был довольно простым:

 data "template_file" "kubeconfig_template" {  template = "${file("${path.module}/templates/kubeconfig.tpl")}"  vars = {...} }  output "kubeconfig" {  value = data.template_file.kubeconfig_template.rendered }  

а затем переход к модулю GitLab с:

 module "gitlab" {  source = "./gitlab"  kubeconfig = module.kubernetes.kubeconfig }  

и использовать в качестве:

 resource "gitlab_group_variable" "kubeconfig_var" {  value = base64encode(var.kubeconfig)  ... }  

Но как добиться того же для более чем одного файла?

Я вижу, что count это работает и с данными, поэтому я могу определить:

 data "template_file" "kubeconfig_templates" {  count = length(var.namespaces)  template = "${file("${path.module}/templates/kubeconfig.tpl")}"  vars = {...} }  

но тогда output это не поддерживается count , и мой «причудливый» обходной путь с принудительным циклом, похоже, не работает:

 output "kubeconfigs" {  value = [  for namespace in var.namespaces :  data.template_file.kubeconfig_templates[index(var.namespaces, namespace)].rendered  ] }  

У вас есть какие-нибудь идеи, как подойти к такой теме?

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

1. Я также изучал fileset() , но тогда, вероятно, может возникнуть проблема с зависимостью? (Попытка создать переменные в модуле GitLab до создания файлов в модуле Terraform).

2. Могу я спросить, почему вы храните визуализированные файлы как переменные GitLab, а не как артефакты? Это похоже на анти-шаблон, так как у вас может быть несколько конвейеров терраформирования, запущенных одновременно, и это может привести к перезаписи ваших переменных, что приведет к состоянию гонки.

3. Похоже, что вы создаете файл yml (вашу визуализированную конфигурацию), который вы используете в последующем задании (предположительно для развертывания в k8s). Я бы рекомендовал вам использовать этот local_file ресурс, чтобы сохранить результаты визуализации в локальный файл, который вы затем сохраните как артефакт. Когда вашему нижестоящему заданию потребуется выполнить развертывание в k8s, вы извлекаете этот артефакт и запускаете его. Использование переменных в вашем проекте приведет к тому, что каждый конвейер, который вы запускаете, будет использовать эти переменные — передача значений между заданиями/конвейерами таким способом, скорее всего, не будет использоваться по назначению, так как конфигурации будут истекать между конвейерами.

4. Я должен согласиться с @Patrick, это кричит против шаблона, кажется, что вы применяете шаблон дизайна контроллера вида модели (MVC) к коду terraform, все ваши шаблоны находятся в модуле, и вы передаете их другим модулям; это не тот дизайн, который я выбрал бы для terraform … вы просто экспериментируете с модулями, видите, что возможно, или это реальный случай использования в реальном мире? … вероятно, лучше всего добавить весь ваш код (или минимальный пример) на GitHub, где мы сможем ознакомиться с этим дизайном.

5. Да, было бы проще local_file , если бы вы перерисовали свой шаблон и передали его, потому что вы могли бы перебирать файлы, которые присутствовали в качестве артефактов. Как уже было сказано, если это то, что вы действительно хотите сделать, вам лучше использовать for_each блок в родительской конфигурации. Вместо того, чтобы пытаться выполнить цикл внутри одного вызова модуля (и, таким образом, столкнуться с тем фактом, что выходные данные не могут работать в этой ситуации), вы бы вызывали модуль много раз — по одному для каждого созданного вами файла. Затем вы будете использовать каждую цепочку для развертывания k8s.

Ответ №1:

Благодаря вводу @patric из комментариев я переключил «файл шаблона» на «локальный файл», и это решило мою проблему.

Новая форма:

 resource "local_file" "kubeconfigs" {  count = length(var.namespaces)  filename = "${var.namespaces[count.index].name}_kubeconfig"   content = templatefile("${path.module}/templates/kubeconfig.tpl", {  ...  }) }  output "generated_kubeconfigs" {  value = local_file.kubeconfigs }  

переход к модулю GitLab:

 module "gitlab" {  source = "./gitlab"  kubeconfigs = concat(module.kubernetes_dev.generated_kubeconfigs,  module.kubernetes_stg.generated_kubeconfigs) }  

и использовать в качестве:

 resource "gitlab_group_variable" "group_variables_kubeconfigs" {  count = length(var.kubeconfigs)  value = base64encode(var.kubeconfigs[count.index].content)  ... }