Ignoring changes to tags with glob

Hi,

I opened a github issue and was pointed to come here instead. https://github.com/hashicorp/terraform/issues/22295

This is related to https://github.com/hashicorp/terraform/pull/21788 and https://github.com/hashicorp/terraform/issues/21444. I am attempting to create Amazon EKS clusters via terraform and control vpc tags. Per Amazon documentation at https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html

VPC Tagging Requirement

When you create your Amazon EKS cluster, Amazon EKS tags the VPC containing the subnets you specify in the following way so that Kubernetes can discover it:
Key 	Value
kubernetes.io/cluster/<cluster-name> shared

    Key: The <cluster-name> value matches your Amazon EKS cluster's name.
    Value: The shared value allows more than one cluster to use this VPC.

Terraform v0.12.6

With the following block I can create my cluster, but have no control over changing tags in the future

resource "aws_vpc" "test" {                                                                                                                                                    
  cidr_block                       = "${var.vpc_cidr_ipv4}"                                                                                                                  
  assign_generated_ipv6_cidr_block = "true"                                                                                                                                  
  instance_tenancy                 = "default"                                                                                                                               
  enable_dns_support               = true                                                                                                                                    
  enable_dns_hostnames             = true                                                                                                                                    
                                                                                                                                                                             
  tags = {                                                                                                                                                                   
    Name       = "${var.infra_name}_${replace(var.region,"-","")}"
  }

  lifecycle {
    create_before_destroy = true
    ignore_changes        = [
      tags
    ]
  }
}

If I try to revert to the 0.11 style and use a % to glob

resource "aws_vpc" "test" {                                                                                                                                                    
  cidr_block                       = "${var.vpc_cidr_ipv4}"                                                                                                                  
  assign_generated_ipv6_cidr_block = "true"                                                                                                                                  
  instance_tenancy                 = "default"                                                                                                                               
  enable_dns_support               = true                                                                                                                                    
  enable_dns_hostnames             = true                                                                                                                                    
                                                                                                                                                                             
  tags = {                                                                                                                                                                   
    Name       = "${var.infra_name}_${replace(var.region,"-","")}"
  }

  lifecycle {
    create_before_destroy = true
    ignore_changes        = [
      tags["kubernetes.io/%"]
    ]
  }
}
There are some problems with the configuration, described below.                                                                                                             
                                                                                                                                                                             
The Terraform configuration must be valid before initialization so that                                                                                                      
Terraform can determine which modules and providers need to be installed.                                                                                                    
                                                                                                                                                                             
Error: Invalid expression                                                                                                                                                    
                                                                                                                                                                             
  on modules/vpc/vpc.tf line 29, in resource "aws_vpc" "test":                                                                                                                 
  29:       tags["kubernetes.io/%"]                                                                                                                                          

A single static variable reference is required: only attribute access and
indexing with constant keys. No calculations, function calls, template
expressions, etc are allowed here.

Trying a * instead of % produces the following which is incorrect

      ~ tags                             = {                                                                                                                                                                                                                                        
          - "kubernetes.io/cluster/test-us-west-2" = "shared" -> null                                                                                                      
        } 

Could I get some pointers on how to proceed?

Hi @pgporada,

Currently Terraform is only able to ignore exact paths, so you’ll need to write out the full tag names in ignore_changes. For a shared object like a VPC that’s of course not feasible in a decomposed configuration where you can’t predict ahead of time all of the EKS clusters that might be sharing a VPC or subnet, and so unfortunately for the moment ignoring the entire tags map is the only option.

I believe the AWS provider team is considering AWS-provider-specific features for globally ignoring tags with particular names or following particular patterns. I wasn’t able to find a GitHub issue directly for that in a quick search, but the discussion in #3143 seems to be covering similar ground so perhaps that is one to watch. An advantage of that particular implementation approach (having the AWS provider handle it) is that in principle you could centrally define that tags prefixed with kubernetes.io/cluster/ are never managed by Terraform, and the AWS provider could even produce errors if a resource configuration tries to set them anyway, rather than it just silently creating drift.