Динамические теги terraform для ASG и других ресурсов, таких как EFS

Я хотел бы получить динамические теги на ресурсе aws_autoscaling_group, но, в отличие от примера в документации, я пока не знаю, сколько их будет, и теги должны быть предоставлены другим ресурсам. В приведенном ниже примере это будет EFS, но в основном все остальные ресурсы aws будут затронуты.

Итак, установлены следующие строки:

variable "tags" {
  type = "map"

  default = {
    tag1 = "value1"
    tag2 = "value2"
  }
}

resource "aws_autoscaling_group" "asg" {
  name                 = "test-asg"
  launch_configuration = "test-lc"
  min_size             = 1
  max_size             = 1
  min_elb_capacity     = 1
  vpc_zone_identifier  = ["subnet-1234"]
  tags                 = <code_here>
}

resource "aws_efs_file_system" "foo" {
  creation_token = "my-product"
  tags           = "${var.tags}"
}

Я пришел с решением, которое будет поддерживать до x динамические теги. К сожалению, он использует фиктивные теги для заполнения не предоставленных тегов до x,

data "template_file" "test" {
  count    = "9"
  template = "key:@:$${key}:@:value:@:$${value}:@:propagate_at_launch:@:true"

  vars {
    key   = "${element(concat(keys(var.tags), list("unusedtag1", "unusedtag2","unusedtag3","unusedtag4","unusedtag5","unusedtag6","unusedtag7","unusedtag8","unusedtag9")), count.index)}"
    value = "${element(concat(values(var.tags), list("", "","","","","","","","")), count.index)}"
  }
}

locals{
  tag0 = "${split(":@:", data.template_file.test.0.rendered)}"
  tag1 = "${split(":@:", data.template_file.test.1.rendered)}"
  tag2 = "${split(":@:", data.template_file.test.2.rendered)}"
  tag3 = "${split(":@:", data.template_file.test.3.rendered)}"
  tag4 = "${split(":@:", data.template_file.test.4.rendered)}"
  tag5 = "${split(":@:", data.template_file.test.5.rendered)}"
  tag6 = "${split(":@:", data.template_file.test.6.rendered)}"
  tag7 = "${split(":@:", data.template_file.test.7.rendered)}"
  tag8 = "${split(":@:", data.template_file.test.8.rendered)}"

  tags = "${list(
          map(local.tag0[0],local.tag0[1],local.tag0[2],local.tag0[3],local.tag0[4],local.tag0[5]),
          map(local.tag1[0],local.tag1[1],local.tag1[2],local.tag1[3],local.tag1[4],local.tag1[5]),
          map(local.tag2[0],local.tag2[1],local.tag2[2],local.tag2[3],local.tag2[4],local.tag2[5]),
          map(local.tag3[0],local.tag3[1],local.tag3[2],local.tag3[3],local.tag3[4],local.tag3[5]),
          map(local.tag4[0],local.tag4[1],local.tag4[2],local.tag4[3],local.tag4[4],local.tag4[5]),
          map(local.tag5[0],local.tag5[1],local.tag5[2],local.tag5[3],local.tag5[4],local.tag5[5]),
          map(local.tag6[0],local.tag6[1],local.tag6[2],local.tag6[3],local.tag6[4],local.tag6[5]),
          map(local.tag7[0],local.tag7[1],local.tag7[2],local.tag7[3],local.tag7[4],local.tag7[5]),
          map(local.tag8[0],local.tag8[1],local.tag8[2],local.tag8[3],local.tag8[4],local.tag8[5]),
          )}"
}

С этим кодом в ASG я могу использовать tags = ["${local.tags}"], В этом примере ресурсы помечены как

tag1 = value1
tag2 = value2
unusedtag1 = 
unusedtag2 = 
unusedtag3 = 
unusedtag4 = 
unusedtag5 =
unusedtag6 = 
unusedtag7 =  

Я хотел бы иметь решение, которое

  • динамический
  • не использует ненужные теги
  • работает с ASG и другими ресурсами AWS одновременно
  • просто распространяет все теги в ASG на запущенные экземпляры: propagate_on_launch = true

Таким образом, решение должно взять существующие теги и добавить propagate_at_launch ключ к нему, прежде чем добавить его в ASG.

3 ответа

Теперь вы можете использовать Terraform dynamic "tag"блок, чтобы выполнить это. Сначала создайте ресурс данных:

      data "aws_default_tags" "tags" {}

Следующий. вставьте этот ресурс данных в ваш целевой ресурс (например, aws_autoscaling_group:

      resource "aws_autoscaling_group" "foo" {
  desired_capacity          = 1
  force_delete              = true
  health_check_grace_period = 300
  launch_configuration = aws_launch_configuration.foo.name
  max_size             = 4
  min_size             = 1
  name                 = var.resource_name
  placement_group      = aws_placement_group.foo.name
  vpc_zone_identifier  = [aws_subnet.private[*].id]

  dynamic "tag" {
    for_each = data.aws_default_tags.tags.tags
    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }

Затем вы можете использовать aws_ec2_tag ресурс, который также работает с ресурсами, отличными от ec2, в сочетании с атрибутом provider ignore_tags. Пожалуйста, обратитесь к другому ответу, который я дал по этой теме, для получения более подробной информации.

Вы можете создать локальную карту, которая содержит общие теги...

locals {
  shared_tags = "${map(
    "Foo", "1",
    "Bar", "2"
  )}"
}

... и затем примените их (с необязательными объединенными обновлениями), чтобы пометить атрибуты ресурсов:

resource "aws_autoscaling_group" "asg" {
  name                 = "test-asg"
  launch_configuration = "test-lc"
  min_size             = 1
  max_size             = 1
  min_elb_capacity     = 1
  vpc_zone_identifier  = ["subnet-1234"]
  tags                 = "${merge(local.shared_tags, map("Baz", "3"))}"
}

resource "aws_efs_file_system" "foo" {
  creation_token = "my-product"
  tags           = "${merge(local.shared_tags, map("Qux", "4"))}"
}

Подпишитесь на dwmkerr за идею для этого.

Другие вопросы по тегам