Извлечь значения из переменной карты Terraform - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь извлечь значения из переменной карты на основе определенных условий, как показано ниже: -

    Variables.tf File content
    variable "users" {
    type = "map"
    default = {
    "101" = "abc@gmail.com"
    "102" = "def@gmail.com"
    "103" = "xyz@gmail.com"
    "104" = "klm@gmail.com"
    "105" = "pqr@gmail.com"
    "106" = "tuv@gmail.com"
     }
   }

Ниже приведен мой файл main.tf

    module "instance" {
    instance_private_ip = ["11.12.13.x"]
    dns_map = ["y"]
    users = ["z"]
    }

    module "instance2" {
    instance_private_ip = ["11.12.14.a"]
    dns_map = ["b"]
    users = ["c"]
    }

Значение x должно быть всеми четными числами в пользовательских переменных, таких как - 102, 104 и т. д. Значение y должно совпадать с x Значение z должно соответствовать x и y . Значение a должно быть всеми четными числами в пользовательских переменных, таких как - 101, 103 и т. Д. Значение b должно совпадать с a Значение c должно соответствовать a и b . Пример как показано ниже

module "instance" {
    instance_private_ip = ["11.12.13.102", "11.12.13.104", "11.12.13.106"]
    dns_map = ["102","104","106"]
    users = ["def@gmail.com","klm@gmail.com","tuv@gmail.com"]
    }
module "instance2" {
    instance_private_ip = ["11.12.14.101", "11.12.14.103", "11.12.14.105"]
    dns_map = ["101","103","105"]
    users = ["abc@gmail.com","xyz@gmail.com","pqr@gmail.com"]
    }

Я пытаюсь использовать $ {element (var.notebook [count.index])}, но это даст мне имя пользователя, а не левую переменную.

Любая помощь приветствуется

1 Ответ

1 голос
/ 24 января 2020

Выражения for Terraform являются ответом на большинство проблем, связанных с преобразованием и фильтрацией коллекций, и я думаю, что это верно и в этом случае.

locals {
  odd_users = [
    for octet, email in var.users : {
      email               = email
      octet               = octet
      dns_map             = tostring(octet)
      instance_private_ip = cidrsubnet("11.12.14.0/24", octet)
    }
    if (octet % 2) == 1
  ]
  even_users = [
    for octet, email in var.users : {
      email               = email
      octet               = octet
      dns_map             = tostring(octet)
      instance_private_ip = cidrsubnet("11.12.13.0/24", octet)
    }
    if (octet % 2) == 0
  ]
}

module "instance" {
  source = "..."

  instance_private_ip = local.even_users[*].instance_private_ip
  dns_map             = local.even_users[*].dns_map
  users               = local.even_users[*].email
}

module "instance2" {
  source = "..."

  instance_private_ip = local.odd_users[*].instance_private_ip
  dns_map             = local.odd_users[*].dns_map
  users               = local.odd_users[*].email
}

В приведенном выше примере два локальных значения сначала фильтруют и преобразуют список, каждое из которых создает список объектов, описывающих пользователей. Затем в двух module блоках я использовал выражения-сплат , чтобы превратить это обратно в плоский список строк, как вы призывали в своем примере,


Вместо определения трех отдельных переменные в вашем дочернем модуле, которые все должны иметь одинаковую длину и индексы, я бы предложил переработать этот интерфейс, чтобы вместо этого взять один список объектов. Вы можете определить переменную users в своем дочернем модуле следующим образом:

variable "users" {
  type = list(object({
    email               = string
    dns_map             = string
    instance_private_ip = string
  }))
}

Определив ее так, вы можете просто передавать локальные значения непосредственно в вызовы модуля:

module "instance" {
  source = "..."

  users = local.even_users
}

module "instance2" {
  source = "..."

  users = local.odd_users
}

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

...