Динамическая интерполяция всех компонентов функции cidrsubnet в Terraform - PullRequest
0 голосов
/ 07 ноября 2019

Есть ли способ в Terraform, где я могу интерполировать все три компонента функции cidrsubnet? Я спрашиваю об этом потому, что хочу создать VPC с другим префиксом CIDR и, соответственно, функция cidrsubnet позаботится о создании подсетей для меня.

Предположительно, VPC " prod " имеет CIDR 10.10.0.0/16, а VPC " dev " имеет CIDR 10.20.0.0/24. Я ищу решение, в котором тот же код будет создавать подсети для меня путем интерполяции значений функции cidrsubnet, как показано ниже:

# map for different CIDR

variable "VPC_CIDR" {
    type = "map"
    default = {
        "dev" = "10.10.0.0/24"
        "prod" = "10.10.0.0/16"
    }
}

variable "PRI_SUBNET_COUNT" {
  default = "1"
}

# intended logic which interpolates netnum (impractical code)

if var.VPC_CIDR = "prod"
  netnum = 4
elif var.VPC_CIDR = "dev"
  netnum = 3   
else 
  netnum = 2

resource "aws_subnet" "sub-node-private" {
    count = var.PRI_SUBNET_COUNT
    cidr_block = cidrsubnet(var.VPC_CIDR, var.netnum, count.index + 2) #all three components interpolated

Приведенный выше код создаст CIDR подсети 10.10.0.0/20 для prod и 10.10.0.0/28 для разработчиковТаким образом, мой код остается тем же самым, только переменные интерполируются.

Примечание: этот код предназначен для демонстрации. Известно, что это не практичный код для if / else в Terraform.

1 Ответ

2 голосов
/ 07 ноября 2019

Если ключи var.VPC_CIDR выбираются вызывающей стороной, то может быть лучше объединить префикс CIDR и количество новых битов, которые будут использоваться для его подсетей, вместе в переменной. Поскольку обычный способ именования переменных Terraform осуществляется строчными буквами, я собираюсь также переименовать его в vpc_cidr в следующих примерах.

variable "vpc_cidr" {
  type = map(object({
    cidr_block  = string
    subnet_bits = number
  }))
  default = {
    dev = {
      cidr_block  = "10.10.0.0/24"
      subnet_bits = 3
    }
    prod = {
      cidr_block  = "10.10.0.0/16"
      subnet_bits = 4
    }
  }
}

variable "pri_subnet_count" {
  type    = number
  default = 1
}

locals {
  vpc_subnets = flatten([
    for name, vpc in var.vpc_cidr : [
      for i in count(var.pri_subnet_count) : {
        name        = "${name}-${i}"
        vpc_name    = name
        cidr_block  = vpc.cidr_block
        subnet_bits = vpc.subnet_bits
        network_num = i + 2
      }
    ]
  ])
}

resource "aws_vpc" "example" {
  for_each = var.vpc_cidr

  cidr_block = each.value.cidr_block
}

resource "aws_subnet" "private" {
  for_each = { for s in local.vpc_subnets : s.name => s }

  vpc_id     = aws_vpc.example[each.value.vpc_name].id
  cidr_block = cidrsubnet(each.value.cidr_block, each.value.subnet_bits, each.value.network_num)
  # ...
}

Если имена «prod» и «dev» являются фиксированнымии, таким образом, ваш модуль будет предполагать, что они всегда будут указаны, вы можете автоматически получить значения subnet_bits способом, аналогичным описанному вами, например:

variable "vpc_cidr" {
  type = object({
    # Force caller to provide "dev" and "prod" values, so
    # that it will match up with the attributes in
    # local.subnet_bits defined below.
    dev  = string
    prod = string
  })
  value = {
    dev = "10.10.0.0/24"
    prod = "10.10.0.0/16"
  }
}

variable "pri_subnet_count" {
  type    = number
  default = 1
}

locals {
  subnet_bits = {
    dev  = 3
    prod = 4
  }

  vpcs = {
    for name, cidr_block in var.vpc_cidr : name => {
      cidr_block  = cidr_block
      subnet_bits = local.subnet_bits[name]
    }
  }

  vpc_subnets = flatten([
    for name, vpc in local.vpcs : [
      for i in count(var.pri_subnet_count) : {
        name        = "${name}-${i}"
        vpc_name    = name
        cidr_block  = vpc.cidr_block
        subnet_bits = vpc.subnet_bits
        network_num = i + 2
      }
    ]
  ])
}

resource "aws_vpc" "example" {
  for_each = local.vpcs

  cidr_block = each.value.cidr_block
}

resource "aws_subnet" "private" {
  for_each = { for s in local.vpc_subnets : s.name => s }

  vpc_id     = aws_vpc.example[each.value.vpc_name].id
  cidr_block = cidrsubnet(each.value.cidr_block, each.value.subnet_bits, each.value.network_num + 2)
  # ...
}

Общая схема, показанная выше, строитструктура данных local.vpc_subnets, которая содержит один элемент для каждой подсети, которую вы хотите создать. Это позволяет затем повторять aws_subnet.private для каждого элемента и собирать вместе все значения, необходимые для заполнения аргументов vpc_id и cidr_block в подсети.

...