Why do the resources change so much after upgrading to v0.12.7

I have upgraded terraform version from v0.11.14 to v0.12.7.

I don’t change .tf file, and it shows great changes.

terraform plan

Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.ec2.aws_instance.this[0] must be replaced
-/+ resource "aws_instance" "this" {
        ami                          = "ami-0135f076a31azdvew"
      ~ arn                          = "arn:aws:ec2:us-west-2:685944ef012277102:instance/i-0256e6b4b98ae244fbe" -> (known after apply)
        associate_public_ip_address  = true
      ~ availability_zone            = "us-west-2c" -> (known after apply)
      ~ cpu_core_count               = 1 -> (known after apply)
      ~ cpu_threads_per_core         = 1 -> (known after apply)
        disable_api_termination      = false
        ebs_optimized                = false
        get_password_data            = false
      + host_id                      = (known after apply)
      ~ id                           = "i-0256e6b4b98w3a244fbe" -> (known after apply)
      ~ instance_state               = "running" -> (known after apply)
        instance_type                = "t2.nano"
        ipv6_address_count           = 0
        ipv6_addresses               = []
      + key_name                     = (known after apply)
        monitoring                   = false
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      ~ primary_network_interface_id = "eni-0eec9804d9wefd15d1f9" -> (known after apply)
      ~ private_dns                  = "ip-127-1-1-2.us-west-2.compute.internal" -> (known after apply)
      ~ private_ip                   = "127-1-1-2" -> (known after apply)
      ~ public_dns                   = "ec2-127-1-1-2.us-west-2.compute.amazonaws.com" -> (known after apply)
      ~ public_ip                    = "127-1-1-2" -> (known after apply)
      ~ security_groups              = [
          - "terraform_example",
        ] -> (known after apply)
        source_dest_check            = true
      ~ subnet_id                    = "subnet-d93da8680" -> "subnet-53de39336" # forces replacement
      ~ tags                         = {
          ~ "Name" = "terraform_example-test-use1-1" -> "example-test-usw2-1"
        }
        tenancy                      = "default"
        user_data                    = "b271f411a1a18ee558650a55b5awec2615753956e7b"
      ~ volume_tags                  = {} -> (known after apply)
      ~ vpc_security_group_ids       = [
          - "sg-00e0fca06we55717e6f",
        ] -> (known after apply)

      - credit_specification {
          - cpu_credits = "standard" -> null
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      ~ root_block_device {
            delete_on_termination = true
          ~ encrypted             = false -> (known after apply)
          ~ iops                  = 100 -> (known after apply)
          + kms_key_id            = (known after apply)
          ~ volume_id             = "vol-0d5f0cbwef1e9d057619" -> (known after apply)
            volume_size           = 30
            volume_type           = "gp2"
        }

      - timeouts {}
    }

  # module.security_group.aws_security_group.this must be replaced
-/+ resource "aws_security_group" "this" {
      ~ arn                    = "arn:aws:ec2:us-west-2:6859440we77102:security-group/sg-00e0fca0655717weae6f" -> (known after apply)
        description            = "Security group for example usage with EC2 instance"
      ~ egress                 = [
          - {
              - cidr_blocks      = [
                  - "0.0.0.0/0",
                ]
              - description      = "All protocols"
              - from_port        = 0
              - ipv6_cidr_blocks = [
                  - "::/0",
                ]
              - prefix_list_ids  = []
              - protocol         = "-1"
              - security_groups  = []
              - self             = false
              - to_port          = 0
            },
        ] -> (known after apply)
      ~ id                     = "sg-00e0fcawef0655717e6f" -> (known after apply)
      ~ ingress                = [
          - {
              - cidr_blocks      = [
                  - "0.0.0.0/0",
                ]
              - description      = "All IPV4 ICMP"
              - from_port        = -1
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "icmp"
              - security_groups  = []
              - self             = false
              - to_port          = -1
            },
          - {
              - cidr_blocks      = [
                  - "0.0.0.0/0",
                ]
              - description      = "HTTP"
              - from_port        = 80
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = []
              - self             = false
              - to_port          = 80
            },
          - {
              - cidr_blocks      = [
                  - "0.0.0.0/0",
                ]
              - description      = "SSH"
              - from_port        = 22
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = []
              - self             = false
              - to_port          = 22
            },
        ] -> (known after apply)
      ~ name                   = "terraform_example" -> "example-aws" # forces replacement
      ~ owner_id               = "685944077wea102" -> (known after apply)
        revoke_rules_on_delete = false
      ~ tags                   = {
          ~ "Name" = "terraform_example" -> "example-aws"
        }
        vpc_id                 = "vpc-38c7b65wefd"

      - timeouts {}
    }

  # module.security_group.aws_security_group_rule.egress_rules[0] must be replaced
-/+ resource "aws_security_group_rule" "egress_rules" {
        cidr_blocks              = [
            "0.0.0.0/0",
        ]
        description              = "All protocols"
      ~ from_port                = 0 -> -1
      ~ id                       = "sgrule-370848wef3828" -> (known after apply)
        ipv6_cidr_blocks         = [
            "::/0",
        ]
        prefix_list_ids          = []
        protocol                 = "-1"
      ~ security_group_id        = "sg-00e0fca0wef655717e6f" -> (known after apply) # forces replacement
        self                     = false
      + source_security_group_id = (known after apply)
      ~ to_port                  = 0 -> -1
        type                     = "egress"
    }

  # module.security_group.aws_security_group_rule.ingress_rules[0] must be replaced
-/+ resource "aws_security_group_rule" "ingress_rules" {
        cidr_blocks              = [
            "0.0.0.0/0",
        ]
        description              = "HTTP"
        from_port                = 80
      ~ id                       = "sgrule-40643wef35381" -> (known after apply)
        ipv6_cidr_blocks         = []
        prefix_list_ids          = []
        protocol                 = "tcp"
      ~ security_group_id        = "sg-00e0fca06wef55717e6f" -> (known after apply) # forces replacement
        self                     = false
      + source_security_group_id = (known after apply)
        to_port                  = 80
        type                     = "ingress"
    }

  # module.security_group.aws_security_group_rule.ingress_rules[1] must be replaced
-/+ resource "aws_security_group_rule" "ingress_rules" {
        cidr_blocks              = [
            "0.0.0.0/0",
        ]
        description              = "All IPV4 ICMP"
        from_port                = -1
      ~ id                       = "sgrule-2903wef01592" -> (known after apply)
        ipv6_cidr_blocks         = []
        prefix_list_ids          = []
        protocol                 = "icmp"
      ~ security_group_id        = "sg-00e0weffca0655717e6f" -> (known after apply) # forces replacement
        self                     = false
      + source_security_group_id = (known after apply)
        to_port                  = -1
        type                     = "ingress"
    }

  # module.security_group.aws_security_group_rule.ingress_rules[2] must be replaced
-/+ resource "aws_security_group_rule" "ingress_rules" {
        cidr_blocks              = [
            "0.0.0.0/0",
        ]
        description              = "SSH"
        from_port                = 22
      ~ id                       = "sgrule-115412wef4704" -> (known after apply)
        ipv6_cidr_blocks         = []
        prefix_list_ids          = []
        protocol                 = "tcp"
      ~ security_group_id        = "sg-00e0fcwefa0655717e6f" -> (known after apply) # forces replacement
        self                     = false
      + source_security_group_id = (known after apply)
        to_port                  = 22
        type                     = "ingress"
    }

That doesn’t make sense! Why?

Hi @lyc0221,

By looking for the # forces replacement annotations on some of the changes we can see which attributes are the root cause for these changes. The other attribute updates here are the result of the plan to replace the objects.

  # module.ec2.aws_instance.this[0] must be replaced
-/+ resource "aws_instance" "this" {
       # ....
       ~ subnet_id = "subnet-d93da8680" -> "subnet-53de39336" # forces replacement
    }

  # module.security_group.aws_security_group.this must be replaced
-/+ resource "aws_security_group" "this" {
      # ...
      ~ name = "terraform_example" -> "example-aws" # forces replacement
    }

This suggests that both the subnet ID and the name have changed. Just upgrading Terraform should not have caused these changes alone, so it would help if you could share the configuration for these two resources before and after your Terraform 0.12 upgrade to try to understand why the security group name became "example-aws" instead of "terraform_example" and why the subnet ID changed from "subnet-d93da8680" to "subnet-53de39336".