Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default_tags always shows an update #18311

Closed
acdha opened this issue Mar 19, 2021 · 80 comments
Closed

default_tags always shows an update #18311

acdha opened this issue Mar 19, 2021 · 80 comments
Labels
service/ec2 Issues and PRs that pertain to the ec2 service.
Milestone

Comments

@acdha
Copy link
Contributor

acdha commented Mar 19, 2021

Description

I have been looking forward to the default tagging support and tested it on a project yesterday which uses https://github.com/terraform-aws-modules/terraform-aws-vpc/ — this immediately showed some tags on aws_vpc and aws_subnet resources as having been changed, but only if another unrelated change was also present.

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform CLI and Terraform AWS Provider Version

Terraform v0.14.8
+ provider registry.terraform.io/hashicorp/aws v3.33.0
+ provider registry.terraform.io/hashicorp/dns v3.1.0
+ provider registry.terraform.io/hashicorp/http v2.1.0

Affected Resource(s)

  • aws_subnet
  • aws_vpc

Terraform Configuration Files

provider "aws" {
  region = var.region

  default_tags {
    tags = local.tags
  }
}

Debug Output

Expected Behavior

No changes would be displayed

Actual Behavior

If an unrelated resource triggers a diff, all of the subnet and VPC resources will show an update in-place diff showing the tags which are already present. Curiously, in my project it lists 5 tags which are present as having been changed but then display a “1 unchanged element hidden”

  # module.vpc.aws_subnet.public[0] will be updated in-place
  ~ resource "aws_subnet" "public" {
        id                              = "subnet-07620b925b0c70066"
      ~ tags                            = {
          + "Environment"        = "Development"
          + "Project"            = "…"
          + "ResponsibleParty"   = "…"
          + "Terraform"          = "true"
          + "TerraformWorkspace" = "…"
            # (1 unchanged element hidden)
        }
        # (10 unchanged attributes hidden)
    }

Steps to Reproduce

  1. terraform apply

References

@ghost ghost added the service/ec2 Issues and PRs that pertain to the ec2 service. label Mar 19, 2021
@github-actions github-actions bot added the needs-triage Waiting for first response or review from a maintainer. label Mar 19, 2021
@anGie44 anGie44 self-assigned this Mar 22, 2021
@anGie44 anGie44 added thinking and removed needs-triage Waiting for first response or review from a maintainer. labels Mar 22, 2021
@anGie44
Copy link
Contributor

anGie44 commented Mar 22, 2021

Hi @acdha, thank you raising this issue! do you mind providing additional configuration details regarding the unrelated resource [that] triggers a diff (and if possible, what event triggered the diff) as well as the configuration for the aws_subnet resource?

@anGie44 anGie44 added the waiting-response Maintainers are waiting on response from community or contributor. label Mar 22, 2021
@acdha
Copy link
Contributor Author

acdha commented Mar 23, 2021

Hi @acdha, thank you raising this issue! do you mind providing additional configuration details regarding the unrelated resource [that] triggers a diff (and if possible, what event triggered the diff) as well as the configuration for the aws_subnet resource?

Basically if nothing else has changed, Terraform will show no changes and naturally no diff. If any other resource has changed when it triggers the plan display for that resource it will also include the resources listed above.

The subnet configuration is here:

https://github.com/terraform-aws-modules/terraform-aws-vpc/blob/997cba4053bd8b4a5d2aed528073b8f02c013e93/main.tf#L367-L420

My invocation of that is somewhat complicated:

module "vpc" {
  source                 = "terraform-aws-modules/vpc/aws"
  version                = "~> 2.69"
  name                   = local.deployment_id
  tags                   = local.tags
  cidr                   = local.vpc_cidr_allocation
  azs                    = slice(data.aws_availability_zones.available.names, 0, 4)
  public_subnets         = cidrsubnets(local.public_cidr, 2, 2, 2, 2)
  private_subnets        = cidrsubnets(local.private_cidr, 2, 2, 2, 2)
  enable_nat_gateway     = true
  single_nat_gateway     = false
  one_nat_gateway_per_az = true
  enable_dns_hostnames   = true
  nat_eip_tags           = { Name = "${local.deployment_id} NAT Gateway" }
  igw_tags               = { Name = "${local.deployment_id} Public Internet Gateway" }

  # We won't use the default network ACL but we want to make sure that it has
  # a safe configuration by default just in case new resources are launched in
  # it for any reason:
  manage_default_network_acl = true
  default_network_acl_name   = "${local.deployment_id}-default"
  # Leaving these as empty lists will result in no rules being applied, leaving
  # the AWS default deny-all rules:
  default_network_acl_ingress = []
  default_network_acl_egress  = []

  public_dedicated_network_acl   = true
  private_dedicated_network_acl  = true
  database_dedicated_network_acl = true

  public_inbound_acl_rules = concat(
…
  )

  public_outbound_acl_rules = concat(
…
  )

  private_inbound_acl_rules = concat(
…
  )

  private_outbound_acl_rules = concat(
…
  )

  enable_s3_endpoint               = true
  enable_efs_endpoint              = true
  enable_ses_endpoint              = true
  efs_endpoint_private_dns_enabled = true
  efs_endpoint_security_group_ids  = [aws_security_group.vpc_endpoints.id]
  ses_endpoint_private_dns_enabled = true
  ses_endpoint_security_group_ids  = [aws_security_group.vpc_endpoints.id]
  ses_endpoint_subnet_ids          = data.aws_subnet_ids.private_subnets.ids
}

The resulting resources look like this:

resource "aws_subnet" "public" {
    arn                             = "arn:aws:ec2:us-east-1:…:subnet/subnet-…"
    assign_ipv6_address_on_creation = false
    availability_zone               = "us-east-1d"
    availability_zone_id            = "use1-az1"
    cidr_block                      = "…/26"
    id                              = "subnet-…"
    map_customer_owned_ip_on_launch = false
    map_public_ip_on_launch         = true
    owner_id                        = ""
    tags                            = {
        "Name" = "…-public-us-east-1d"
    }
    tags_all                        = {
        "Environment"        = "Development"
        "Name"               = "…-public-us-east-1d"
        "Project"            = ""
    }
    vpc_id                          = "vpc-…"
}

I notice this a lot because of #14892 — this project also has some IAM policies which are defined using the ARNs of an ECS cluster and that means that those always show an update in-place even though all of the information is available at plan time.

  # module.collection_access.data.aws_iam_policy_document.ecs_update_service will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "ecs_update_service"  {
      ~ id      = "83089849" -> (known after apply)
      ~ json    = jsonencode(
            {
              - Statement = [
                  - {
                      - Action   = "ecs:UpdateService"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:ecs:us-east-1:…:service/…/collection-access"
                      - Sid      = ""
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
      - version = "2012-10-17" -> null

      ~ statement {
          - effect        = "Allow" -> null
          - not_actions   = [] -> null
          - not_resources = [] -> null
            # (2 unchanged attributes hidden)
        }
    }

  # module.collection_access.aws_iam_policy.ecs_update_service will be updated in-place
  ~ resource "aws_iam_policy" "ecs_update_service" {
        id     = "arn:aws:iam::630942203890:policy/…-ECS-updatecollection-access-service"
        name   = "…-ECS-updatecollection-access-service"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action   = "ecs:UpdateService"
                      - Effect   = "Allow"
                      - Resource = "arn:aws:ecs:us-east-1:630942203890:service/…/collection-access"
                      - Sid      = ""
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (2 unchanged attributes hidden)
    }

@bflad
Copy link
Contributor

bflad commented Apr 12, 2021

Hi @acdha 👋 Does the difference disappear if you no longer declare tags = local.tags in the module block? I'm able to reproduce this behavior with the following:

# main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.36.0"
    }
  }
  required_version = ">= 0.14.10"
}

locals {
  tags = {
    sometagkey = "sometagvalue"
  }
}

provider "aws" {
  region = "us-east-2"

  default_tags {
    tags = local.tags
  }
}

module "test" {
  source = "./mod"

  providers = {
    aws = aws
  }

  name = "defaulttagstest"
  tags = local.tags
}

# mod/main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 3.33.0"
    }
  }
  required_version = ">= 0.14.10"
}

variable "name" {
  description = "Name to be used on all the resources as identifier"
  type        = string
  default     = ""
}

variable "tags" {
  description = "A map of tags to add to all resources"
  type        = map(string)
  default     = {}
}

resource "aws_vpc" "this" {
  cidr_block = "10.0.0.0/16"

  tags = merge(
    {
      "Name" = format("%s", var.name)
    },
    var.tags,
  )
}

resource "aws_subnet" "this" {
  cidr_block = cidrsubnet(aws_vpc.this.cidr_block, 8, 0)
  vpc_id     = aws_vpc.this.id

  tags = merge(
    {
      "Name" = format("%s", var.name)
    },
    var.tags,
  )
}

Applying twice:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # module.test.aws_subnet.this will be updated in-place
  ~ resource "aws_subnet" "this" {
        id                              = "subnet-00939145cc72a2791"
      ~ tags                            = {
          + "sometagkey" = "sometagvalue"
            # (1 unchanged element hidden)
        }
        # (10 unchanged attributes hidden)
    }

  # module.test.aws_vpc.this will be updated in-place
  ~ resource "aws_vpc" "this" {
        id                               = "vpc-07ad2aaf41bd4fada"
      ~ tags                             = {
          + "sometagkey" = "sometagvalue"
            # (1 unchanged element hidden)
        }
        # (13 unchanged attributes hidden)
    }

Plan: 0 to add, 2 to change, 0 to destroy.

The plan difference here is expected in this case as provider-level default tags are removed from the underlying resource tags value automatically during refresh if the tag key and value exactly match. This is happening since the tags configuration is still being passed via the module tags variable which is eventually merged that into the resource block tags argument, making the tags configuration exactly redundant. While we could theoretically detect and handle this situation, it would hide this type of configuration issue and require logic in every resource implementation.

@acdha
Copy link
Contributor Author

acdha commented Apr 13, 2021

I think that's correct. If I remove the tags option, I see diffs to remove the tags from resources which I guess do not yet support the provider default tags? The list notably does not include the aws_vpc or aws_subnet resources which are currently tagged like everything else.

aws_default_network_acl
aws_eip
aws_internet_gateway
aws_nat_gateway
aws_network_acl
aws_route_table
aws_vpc_endpoint

@bflad
Copy link
Contributor

bflad commented Apr 13, 2021

Correct, the most recent version only includes default_tags functionality for the aws_vpc and aws_subnet resources for experimentation. We are preparing the rest of the resources now: https://github.com/hashicorp/terraform-provider-aws/pulls?q=is%3Apr+is%3Aopen+%22support+default+tags%22 or can be holistically tracked in the issue: #7926

@acdha
Copy link
Contributor Author

acdha commented Apr 13, 2021

That makes sense — it's a bit messy during the transition period but since what I already works the easiest thing is just to leave it alone until default_tags supports all of the other resource types.

@acdha
Copy link
Contributor Author

acdha commented Apr 30, 2021

I'm inclined to say this can be closed with 3.38.0 since the support for all of the resources types allowed me to make a nice de-boilerplate commit. The only wart I ran into was aws_instance volume_tags (#19188).

@devopsrick
Copy link

The lack of support for volume_tags makes this a pretty painful problem for us.

We currently use the same variable passed in most modules to populate tags and volume_tags, so if we want volume_tags to be populated we will have overlapping tags/tags_all which causes this messy output. Without a ton of module rewrites this means we cannot use default_tags at all. Either this bug or the fact that volume_tags doesn't inherit default_tags really should really be addressed.

The benefits of default_tags is huge, but it will be very painful for us to adopt if one of those two bugs isn't addressed to ease the transition. We cannot have this constant messy plan output (the json output of 'unknown' values is the real pain point for us, it has even exposed secrets), and we cannot have volume_tags not populated, so we are stuck not using default_tags at all.

@acdha
Copy link
Contributor Author

acdha commented May 20, 2021

We currently use the same variable passed in most modules to populate tags and volume_tags, so if we want volume_tags to be populated we will have overlapping tags/tags_all which causes this messy output. Without a ton of module rewrites this means we cannot use default_tags at all. Either this bug or the fact that volume_tags doesn't inherit default_tags really should really be addressed.

I took that rewrite path which wasn't especially terrible for a small project but it meant that I had to keep passing that variable around. It would have been really nice to have a way to get the default_tags attribute from the provider so you could write that code generically.

@olenm
Copy link

olenm commented Jun 14, 2021

Still a major annoyance in aws v3.45.0 - I am surprised this is not marked as a bug?
I'm seeing a default_tag being overwritten (with the same value in some cases) and TF wants to make changes even though the tag exists on the aws-resource and no changes should be applicable.

affected resources (so far):

  • aws_s3_bucket
  • aws_cloudfront_distribution
  • aws_iam_role
  • aws_lambda_function
  • aws_sns_topic
  • aws_kms_key

@kylelaverty
Copy link

If I understand the situation correctly, this is caused by having a tag's name match in the default_tag and tag collections. This is something that is easily fixed if you own the module but might be impossible if you are making use of other people's modules. This should be something that shows up when validate is run as an info level message, just to let people know.

@olenm
Copy link

olenm commented Jul 9, 2021

Well default-tags should be the first layer, any other tags being set should act as an override to a default-tag of the same name-key, and if the value is the same and set already, should not be displayed as a change (where it currently thinks a change is needed). If the default-tag is being overridden by an explicitly set tag, then yes show an info message of some sort.

The problem is enhanced in production environments where TF is claiming a change is to be made, but no changes occur - this is the scary part as the larger your project folder grows, the more potential noise TF shows as "changing" making it harder to see potential mistakes.

@vinicius73
Copy link

Some situation here.
Any news about that?

@rhenning
Copy link
Contributor

rhenning commented Jul 19, 2021

@olenm observed:

... default-tags should be the first layer, any other tags being set should act as an override to a default-tag of the same name-key, and if the value is the same and set already, should not be displayed as a change (where it currently thinks a change is needed). If the default-tag is being overridden by an explicitly set tag, then yes show an info message of some sort.

on the surface what @olenm suggests feels like the most desirable behavior to me -- the implicit equivalent of merge(default_tags{}, resource_tags{}), with a tfplan diff only if that differs from what is in state/refresh. while this seems easy to reason about in the abstract, i recall seeing somewhere that this may be difficult to put into practice because of the way the two are merged in state. can someone shine some light on this?

and also:

The problem is enhanced in production environments where TF is claiming a change is to be made, but no changes occur ... the larger your project folder grows, the more potential noise TF shows as "changing" making it harder to see potential mistakes.

indeed, this is what we're struggling with at the moment. a bunch of reusable inner library modules, composed together by app engineering teams in root modules to build their own unique, opinionated infrastructures. we're in the transition phase of getting everyone on provider >~3.40, using default_tags, and updating the inner modules to remove the duplication, but the signal:noise ratio of tfplan is seriously degraded.

maybe worse, if i understand correctly, this isn't just noise. TF will call the AWS API and perform a CRUD action for every affected resource, despite the fact that nothing has changed. Yes, the modify should end up as a noop, but the behavior wastes network bandwidth, consumes API quota, slows down the apply phase, and increases the chances of something going wrong.

this contrived example below illustrates the issue, though IRL the resource-level tags might be managed within a module. the EC2 API is called with a modify each time plan/apply is executed, though nothing has changed.

provider "aws" {
  region = "us-east-1"

  default_tags {
    tags = {
      foo = "bar"
      baz = "biddy"
    }
  }
}

data "aws_vpc" "_" {
  default = true
}

resource "aws_security_group" "_" {
  vpc_id = data.aws_vpc._.id
  tags = {
    baz  = "biddy"
    beep = "boop"
  }
}

@jakubigla
Copy link

Is this being looked over? Absolutely annoying issue which is stopping me using default_tags...

@brightshine1111
Copy link

Still seeing this with aws provider v3.60.0 and Terraform 0.15.3 for resources:

  • aws_lb
  • aws_lb_target_group
  • aws_lb_listener
  • aws_ssm_parameter

Even when I configure the provider to ignore all the tag keys, e.g.:

locals {
  tags = {
    foo = "bar"
    baz = "bop"
  }
}

provider "aws" {
  ignore_tags {
    keys = ["foo", "baz"]
  }
}

resource "aws_ssm_parameter" "this" {
  ...
  tags = local.tags
}

the plan still shows this:

Terraform will perform the following actions:

  # aws_ssm_parameter.this will be updated in-place
  ~ resource "aws_ssm_parameter" "this" {
      ~ tags        = {} -> (known after apply)
        # (8 unchanged attributes hidden)
    }

@share-me
Copy link

share-me commented Oct 5, 2021

Ok there is no changes, but still it's unusable in production.
Our operators are in panic mode when this occurs.

  # module.vault.aws_secretsmanager_secret.vault[0] has been changed
  ~ resource "aws_secretsmanager_secret" "vault" {
        id                             = "arn:aws:secretsmanager:eu-west-3:0000000000:secret:vault_prod-1d24E12"
        name                           = "vault_prod"
      + tags                           = {}
        # (6 unchanged attributes hidden)
    }
(...)
No changes. Your infrastructure matches the configuration.
(...)

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

@DemiAHMS
Copy link

DemiAHMS commented Oct 5, 2021

Just found this bug when attempting to manage aws_iam_user.

$ terraform version
Terraform v1.0.8
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v3.61.0

This is the entirety of the terraform config (for this set of resources, see notes at the bottom):

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
  backend "s3" {
    # The S3 bucket where state-files are kept
    bucket = "terraform-statefiles.example.com"

    # DynamoDB tables where the lock is kept
    key = "live/global/iam/terraform.tfstate"

    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

provider "aws" {
  region = "us-east-1"

  default_tags {
    tags = {
      created_by   = "me"
      created_tool = "terraform"
      created_date = formatdate("YYYY-MM-DD", timestamp())
      team         = "..."
      owner        = "team-..."
    }
  }

  ignore_tags {
    keys = ["created_date"]
  }
}

### This is the account alias for the whole account
resource "aws_iam_account_alias" "alias" {
  account_alias = "...example..."
}

resource "aws_iam_user" "root_iam_user" {
  name = "root_iam_user"
}

### IAM group for the admins
resource "aws_iam_group" "root_accounts" {
  name = "root_accounts"
}
resource "aws_iam_group_membership" "group_root_accounts_membership" {
  name = "group_root_accounts_membership"

  users = [
    aws_iam_user.root_iam_user.name,
  ]

  group = aws_iam_group.root_accounts.name
}

resource "aws_iam_group_policy_attachment" "admin_access" {
  group      = aws_iam_group.root_accounts.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
resource "aws_iam_group_policy_attachment" "billing_access" {
  group      = aws_iam_group.root_accounts.name
  policy_arn = "arn:aws:iam::aws:policy/job-function/Billing"
}

Gives output:

$ terraform fmt ; terraform plan

Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # aws_iam_user.root_iam_user has been changed
  ~ resource "aws_iam_user" "root_iam_user" {
        id            = "root_iam_user"
        name          = "root_iam_user"
      ~ tags          = {
          + "created_by"   = "me"
          + "created_tool" = "terraform"
          + "owner"        = "team-..."
          + "team"         = "..."
        }
        # (5 unchanged attributes hidden)
    }

Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to
these changes.

──────────────

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_iam_user.root_iam_user will be updated in-place
  ~ resource "aws_iam_user" "root_iam_user" {
        id            = "root_iam_user"
        name          = "root_iam_user"
      ~ tags          = {
          + "created_date" = "2021-10-04"
            # (4 unchanged elements hidden)
        }
        # (5 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

And this persists even with terraform apply with yes, and immediately do it again.

Notes about my environment:

  • the user "root_iam_user" mentioned in the code blocks above, is the user that I am currently using to run terraform
  • I know for sure that I'm the only person using terraform, because no one else has access.

Update:
This issue persists, even when I add ALL the tags to ignore_tags.

Update 2:
I retried tfplan / tfapply on my other modules that had appeared fine, and now they show the same behavior mentioned here

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

So it appears that the first time I setup with default_tags / ignore_tags, it works as intended, and repeated times show the anomalous behavior.

@Grasume
Copy link

Grasume commented Oct 11, 2021

This does not just Show with ECS but Multiple different services , From ECS to lb and rds dbs

@onisim-iacob
Copy link

onisim-iacob commented Jan 10, 2023

I think I found a workaround. I kind of bypassed this issue by creating a new aws "provider" without the default-tags, and tagging only the bugged resources manually using a "locals" definition.

  • provider.tf
# provider with default tags
provider "aws" {
  region              = "eu-west-1"
  version = "~> 3.0"
  default_tags {
    tags = {
      Environment         = var.environment
      Project             = var.project
    }
  }
}

# provider without tags and an "alias"
provider "aws" {
  region              = "eu-west-1"
  alias               = "no-default-tags"
  version = "~> 3.0"
}

I wanted to create a variable "tags" with a map inside, but you can't create variables within a variable so I defined a "locals" instead:

  • vars.tf
variable "environment" {
  description = "Short description environmet: dev, stg or prd"
  default = "dev"
}

variable "project" {
  description = "Name of project"
  default = "test"
}

# Workaround to default-tags bug https://github.com/hashicorp/terraform-provider-aws/issues/18311
locals {
  tags = {
          Environment         = "${var.environment}"
          Project             = "${var.project}"
  }
}

Tag only the bugged resources. In my case it happened with "aws_s3_bucket". Use the provider "no-default-tags" and merge the tags you want with local.tags.

  • main.tf
resource "aws_s3_bucket" "bucket" {
  provider = aws.no-default-tags
  bucket = var.domain_web
  tags = merge(
    {
      "Name" = "${var.environment}-${var.domain_web}-s3"
    }, local.tags
  )
}
  • Pros: You bypass the bugged resources and you will get "No changes. Infrastructure is up-to-date."
  • Cons: You have to "cherrypick" and edit a few files on the resources that present this problem.

PD: You can find more examples of how to use the default-tags on this repo: https://github.com/rocketinsights/terraform-blog-default-tags and this video https://www.youtube.com/watch?v=F9eKnx3l8KA

  • Before my workaround:
    image

  • After my workaround:
    image

@simnalamburt
Copy link

Great work @onisim-iacob. I've been waiting for the workaround so much!

@DenisBY
Copy link

DenisBY commented Jan 19, 2023

To my mind, it's not a workaround. It worked like this before default_tags when you had to define tags for every resource. The purpose of default_tags is that you don't have to define tags for every resource and these tags are applied automatically to all resources which support tagging.

@onisim-iacob
Copy link

You can try @2rs2ts solution, but in my opinion, it is hard to understand. In my case I had only a couple of resources bugged and this "worked around" the bug. In all cases, you have to edit the TF code unless the AWS provisioner will get an official fix.

@simnalamburt
Copy link

I'm willing to fix this by fixing the Terraform AWS provider myself. Could any of the maintainers of this project give me even the slightest hint as to how this problem is happening or what code I can fix? With a little help, I'll try to solve it myself. It seems now is the time to narrow down the problem by having a constructive conversation rather than asking the project maintainer to solve it.

@mossad-zika
Copy link

mossad-zika commented Feb 10, 2023

@morremeyer you are stating that

Comments like “+1“, “Same here” etc. do not help

But what can really help? The issue is almost 2 years old and you have plenty of thumbs up

Do not use "default_tags" - is not an answer and I can't accept it as a permanent solution

It doesn't make any sense, really

@morremeyer
Copy link
Contributor

@mossad-zika If you urgently need a solution, please talk to the Hashicorp support directly about prioritizing this.
Spamming others in an issue does not help, it frustrates maintainers and external users.

@jwshieldsGetty
Copy link

I don't want to add a "+1" here - but I've also found that this seems to affect aws_cloudwatch_metric_alarm as well

@CasaSky
Copy link

CasaSky commented May 11, 2023

i can confirm that updating terraform to version 1.4.6 solves the issue described above. Although before the update i realized that all resources were affected not only vpc and subnet.

@johnsonaj
Copy link
Contributor

Issue resolved in #30793 and merged to main in #31392. Will be released in v5.0.0

@sbocinec
Copy link
Contributor

@johnsonaj by chance, is it going to be back-ported to v4 version of the provider?

@github-actions
Copy link

This functionality has been released in v5.0.0 of the Terraform AWS Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!

@neelaruban
Copy link

@johnsonaj i have pinned my versions to the latest provider version 5.0.1 however i could still see updates for the tags even though there were not any changes to the module .

@2rs2ts
Copy link
Contributor

2rs2ts commented Jun 6, 2023

@neelaruban just checking, since I was about to go make changes to update my provider version and I saw your message... do you see the update on subsequent applies? Maybe it's just a one-time diff and once you apply with the 5.x provider it will stop being a permadiff? I'd like to hear if it's still a problem for you before I go do the work to upgrade my repos. 😅

@johnsonaj
Copy link
Contributor

@johnsonaj i have pinned my versions to the latest provider version 5.0.1 however i could still see updates for the tags even though there were not any changes to the module .

@neelaruban thanks for the update. I have tried a few different configurations and I am unable to produce perpetual diffs. Would it be possible to submit a new issue, with an example of your configuration?

It is important to note the following about this update to default_tags and tags

It is still not possible to have computed values in the provider level default_tags block. This is due to limitations on how the provider is configured and how these default_tags are applied to resources downstream. All values in default_tags must be known values. These can then be overwritten on the resource itself.

The following configuration is possible:

provider "aws" {
  region = "us-west-2"
  default_tags {
    tags = {
      created_at = "placeholder time"
    }
  }
}

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"
  tags = {
    created_at = timestamp()
  }
}

However, the follow will still not compute correctly because default_tags must be known values

provider "aws" {
  region = "us-west-2"
  default_tags {
    tags = {
      created_at = timestamp()
    }
  }
}

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"
  tags     = {
    additional_tag = "value
  }
}

@TimothyLoyer
Copy link
Contributor

@johnsonaj i have pinned my versions to the latest provider version 5.0.1 however i could still see updates for the tags even though there were not any changes to the module .

@neelaruban just checking, since I was about to go make changes to update my provider version and I saw your message... do you see the update on subsequent applies? Maybe it's just a one-time diff and once you apply with the 5.x provider it will stop being a permadiff? I'd like to hear if it's still a problem for you before I go do the work to upgrade my repos. sweat_smile

I had to apply once and then on subsequent plan/apply runs I have seen no changes. I'm operating under the assumption that the state needed to be updated once to accurately calculate diffs on followup runs?

@nantiferov
Copy link
Contributor

state needed to be updated once to accurately calculate diffs on followup runs?

Seems so, also had to apply once after update to provider v5.x and then all next runs were without diffs.

@neelaruban
Copy link

neelaruban commented Jun 14, 2023

@johnsonaj I am not using a dynamic value as you have shown for the default tags at the provider level , to give it a more context this how my provider configurations look at the moment

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "5.0.0"
    }
  }
}

provider "aws" {
  region = "af-south-1"
  ignore_tags {
   key_prefixes = ["VVVVVV","XXX","VVVVV","CCVVVV"]
  } 
}

another thing to note is that i am not running terraform apply to my plans , i am still running the plans to see if my changes to the pinning down the version works or not . However looking at the comments from @2rs2ts @TimothyLoyer and @nantiferov proves a point that we have to apply first then the subsequent runs will be without any updates .

thanks all

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
service/ec2 Issues and PRs that pertain to the ec2 service.
Projects
None yet
Development

No branches or pull requests