amazon-web-servicesterraformterraform-provider-aws

terraform tags for list variable not working


trying to create aws resources , i get problems in tags , can some one please help but i want to merge tags with local.tags and with the addition tags for the resource creation , i think something to do with list and object ,

provider "aws" {
  region = var.aws_region
  default_tags {
    tags = local.tags
  }
}

locals {

   tags = {
    Application     = var.stack
    Owner           = var.owner
    CostCenter      = var.cost_center
    Project         = var.stack
    environmentCode = var.environment_code
    Environment     = var.environment
    Cmdb            = var.cmdb
  }
}

data "aws_ssm_parameter" "environment" {
  name = "/ss/environment"
}

resource "awscc_elasticache_serverless_cache" "elasticache" {
  serverless_cache_name = "${data.aws_ssm_parameter.environment.value}-serverless-elasticache"
  description           = "Generic ElastiCache Redis Serverless"
  engine                = "redis"
  major_engine_version  = 7
  daily_snapshot_time   = "03:00"
  snapshot_retention_limit = 7
  security_group_ids = ["${aws_security_group.elasticache_access.id}"]
  subnet_ids          = module.vpc_data.subnet_ids
  depends_on = [aws_security_group.elasticache_access]
  kms_key_id            =  data.aws_kms_key.ucm.id
  tags = merge(
    local.tags,
    {
      Name   = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless"
      "Description" = "ECS security group for ${var.stack} running on ${local.environment}"
    },
  )
}

Error:

│ Error: Incorrect attribute value type │ │ on main.tf line 68, in resource "awscc_elasticache_serverless_cache" "elasticache": │ 68: tags = merge( │ 69: local.tags, │ 70: { │ 71: "Name" = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless", │ 72: "Description" = "Elasticache serverless for ucm" │ 73: } │ 74: ) │ ├──────────────── │ │ local.tags is object with 7 attributes │ │ Inappropriate value for attribute "tags": set of object required.

Even as per https://registry.terraform.io/providers/hashicorp/awscc/latest/docs/resources/elasticache_serverless_cache

 tags = [{
    Name   = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless"
    Description = "Elasticache serverless for ucm"
  }]

Error: Incorrect attribute value type │ │ on main.tf line 68, in resource "awscc_elasticache_serverless_cache" "elasticache": │ 68: tags = [{ │ 69: Name = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless" │ 70: Description = "Elasticache serverless for ucm" │ 71: }] │ │ Inappropriate value for attribute "tags": element 0: attribute "key" is │ required.


Solution

  • Based on the documentation you linked, the tags seem to need to be provided with:

      tags = [
        {
          key   = "Name"
          value = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless"
        },
        {
          key   = "Description"
          value = "ECS security group for ${var.stack} running on ${local.environment}"
        }
      ]
    

    In other words, it seems you would need to explicitly define the keyword key for the tag key and value for the tag value. You would have to repeat something similar for the rest of tags you want, but it might work with default_tags as well. Make sure to check that when running terraform plan.

    EDIT: Since all the tags require having the key and value keys, a new local variable elasticache_serverless_tags can be defined like the following:

    locals {
       tags = {
        Application     = var.stack
        Owner           = var.owner
        CostCenter      = var.cost_center
        Project         = var.stack
        environmentCode = var.environment_code
        Environment     = var.environment
        Cmdb            = var.cmdb
      }
    
       elasticache_serverless_tags = [
         {
           key   = "Application"
           value = var.stack
         },
         {
           key   = "Owner"
           value = var.owner
         },
         {
           key   = "CostCenter"
           value = var.cost_center
         },
         {
           key   = "Project"
           value = var.stack
         },
         {
           key   = "environmentCode"
           value = var.environment_code
         },
         {
           key   = "Environment"
           value = var.environment
         },
         {
           key   = "Cmdb"
           value = var.cmdb
         },
      ]
    }
    

    Then, in the resource block:

      tags = toset(concat(local.elasticache_serverless_tags,
      [
        {
          key   = "Name"
          value = "${data.aws_ssm_parameter.environment.value}-ucm-elasticache-serverless"
        },
        {
          key   = "Description"
          value = "ECS security group for ${var.stack} running on ${local.environment}"
        }
      ]))
    

    The old local variable tags has to stay the same since it is referenced in the default_tags which requires having a map.

    EDIT 2: An even easier way, with less code repetition, would be the following:

    locals {
       tags = {
        Application     = var.stack
        Owner           = var.owner
        CostCenter      = var.cost_center
        Project         = var.stack
        environmentCode = var.environment_code
        Environment     = var.environment
        Cmdb            = var.cmdb
      }
    
      elasticsearch_serverless_tags = [for k, v in local.tags : {
        key   = k
        value = v
      }]
    }
    

    The concat and toset would be used the same as in the previous example in the tags argument of the resource.