Terraform создает странный for_each

Я хотел создать цикл for_each, который перебирает только объекты в массиве, у которых есть определенная пара ключ: значение.

Мои входные переменные:

inputs = {
  names = ["first", "second"]
  lifecycle_rules = [
    {
      name = first
      condition = {
        age = "1"
      }
      action = {
        type = "Delete"
      }
    },{
      condition = {
        age = "2"
      }
      action = {
        type = "Delete"
      }
    },
    {
      name = second
      condition = {
        age = "3"
      }
      action = {
        type = "Delete"
      }
    },{
      condition = {
        age = "4"
      }
      action = {
        type = "Delete"
      }
    }
  ]

и в моем main.tf (кстати, для развертывания ведра gcp для справки) я хотел разделить жизненный цикл для каждого ведра и хотел применить только правила, в которых есть имя ведра.

Поэтому, если кто-нибудь знает, как изменить приведенный ниже код for_each, чтобы он работал, я был бы очень признателен. Я считаю, что нужно изменить только for_each, чтобы перебрать нужные элементы (скажем, только объекты в этом списке, у которых name = first). из набора var.lifecycle_rules

  resource "google_storage_bucket" "buckets" {
    count         = length(var.names)
    name          = "${lower(element(var.names, count.index))}"
...
    dynamic "lifecycle_rule" {
     #for_each = length(lookup(lifecycle_rules[lookup(element(var.names, count.index))])
     for_each = lifecycle_rules
     content {
       action {
         type          = lifecycle_rule.value.action.type
         storage_class = lookup(lifecycle_rule.value.action, "storage_class", null)
       }
       condition {
         #age = lifecycle_rule.value.name == element(var.names, count.index) ? lookup(lifecycle_rule.value.condition, "age", null) : null
         age = lookup(lifecycle_rule.value.condition, "age", null) : null
...

person potatopotato    schedule 29.07.2020    source источник
comment
Хотя это вполне возможно (и в документации есть пример того, как это сделать), почему бы просто не перебрать карту lifecycle_rules вместо использования count для длины переменной names? Затем вы можете использовать повторяющиеся значения карты для логики в блоке dynamic, а также для определения того, должен ли он существовать вообще. Так было бы намного проще и чище.   -  person Matt Schuchard    schedule 29.07.2020
comment
да, я хотел это сделать, но весь модуль (большой между ... точками) - это всего лишь один, сделанный в google, предопределенный, и не был уверен, как двойной for_each работает под собой - но будет тестировать - кроме этого, вы могли бы дать ссылку в документы? Я обязательно все проверил? доступные методы и не нашел ни одного, чтобы решить эту проблему   -  person potatopotato    schedule 30.07.2020


Ответы (1)


Я думаю, что этот странный вид можно получить в два этапа.

  1. Преобразовать lifecycle_rules в карту на основе names
variable "input" {

  default = {
  names = ["first", "second"],
  
  lifecycle_rules = [
    {
      name = "first",
      condition = {
        age = "1"
      },
      action = {
        type = "Delete"
      }
    },
    {
      condition = {
        age = "2"
      },
      action = {
        type = "Delete"
      }
    },
    {
      name = "second",
      condition = {
        age = "3"
      },
      action = {
        type = "Delete"
      }
    },
    {
      condition = {
        age = "4"
      },
      action = {
        type = "Delete"
      }
    }
  ]
  }

}



locals {

  new = {
    for name in var.input.names:  
       name => [for rule in var.input.lifecycle_rules: 
        contains(keys(rule), "name" ) ? 
          rule.name == name ? rule: null : 
          null ] 
  }    
}


что даст local.new в виде:

{                                                        
  "first" = [            
    {                 
      "action" = {       
        "type" = "Delete"
      }              
      "condition" = { 
        "age" = "1"
      }                  
      "name" = "first"
    },                   
    null,          
    null,                
    null,                
  ]                  
  "second" = [           
    null,          
    null,                
    {                  
      "action" = {       
        "type" = "Delete"
      }              
      "condition" = {  
        "age" = "3"
      }                
      "name" = "second"
    },   
    null,
  ]
}  

  1. Выполните for_each
  resource "google_storage_bucket" "buckets" {

    for_each = toset(var.input.names)  

    name          = each.key

    dynamic "lifecycle_rule" {

      # iterate for each name skipping null values
      for_each = [for v in local.new[each.key]: v if v != null]
  
      content {
        action {
           type          = lifecycle_rule.value["action"].type
           storage_class = lookup(lifecycle_rule.value["action"], "storage_class", null)
         }

        condition {
            age = lookup( tag.value["condition"], "age", null) 
         }
      }
   }
}

Я мог проверить только первый шаг и частично второй (используя aws_autoscaling_group и его несколько tag компонентов). У меня нет доступа к облаку Google, чтобы полностью протестировать код.

person Marcin    schedule 03.08.2020