title: Terraform constantly forces to recreate the resource (delete then create)
body: <p>I am using terraform + terraform cloud (for remote state management)</p>
  
  <pre><code>✦ ➜ terraform -v                               
  Terraform v0.12.24
  + provider.aws v2.60.0
  + provider.null v2.1.2
  
  </code></pre>
  
  <pre><code>✦ ➜ terraform plan                                     
  Refreshing Terraform state in-memory prior to plan...
  The refreshed state will be used to calculate this plan, but will not be
  persisted to local or remote state storage.
  
  module.vpc.module.vpc.aws_vpc.this[0]: Refreshing state... [id=vpc-0e89e6d2515004e3d]
  module.s3.aws_s3_bucket.project_bucket: Refreshing state... [id=project-bucket]
  data.aws_availability_zones.all: Refreshing state...
  module.bastion.aws_key_pair.ssh_key: Refreshing state... [id=project]
  module.vpc.module.vpc.aws_eip.nat[0]: Refreshing state... [id=eipalloc-053796962073bcc33]
  module.vpc.module.vpc.aws_subnet.private[1]: Refreshing state... [id=subnet-037152cf7128a8a31]
  module.vpc.module.vpc.aws_subnet.private[0]: Refreshing state... [id=subnet-0b4f07b30fb51ab78]
  module.vpc.module.vpc.aws_route_table.private[0]: Refreshing state... [id=rtb-0dd52f77a6da2f2b8]
  module.vpc.module.vpc.aws_subnet.private[2]: Refreshing state... [id=subnet-007658ad3ec49fed8]
  module.vpc.module.vpc.aws_route_table.public[0]: Refreshing state... [id=rtb-050f67e4a3f5b978e]
  module.vpc.module.vpc.aws_subnet.public[1]: Refreshing state... [id=subnet-03b773348ee69e0ec]
  module.vpc.module.vpc.aws_subnet.public[2]: Refreshing state... [id=subnet-088a8a66b9709ef80]
  module.vpc.module.vpc.aws_subnet.public[0]: Refreshing state... [id=subnet-0fd9ca3b8e2220d17]
  module.vpc.module.vpc.aws_internet_gateway.this[0]: Refreshing state... [id=igw-023440c10240ecb89]
  module.bastion.module.bastion_sg.aws_security_group.this_name_prefix[0]: Refreshing state... [id=sg-083a3f9ac371028cc]
  module.vpc.module.vpc.aws_route.public_internet_gateway[0]: Refreshing state... [id=r-rtb-050f67e4a3f5b978e1080289494]
  module.vpc.module.vpc.aws_route_table_association.public[1]: Refreshing state... [id=rtbassoc-03491c0a1e86fb1f4]
  module.vpc.module.vpc.aws_route_table_association.public[0]: Refreshing state... [id=rtbassoc-01d46d6a2886abad7]
  module.vpc.module.vpc.aws_nat_gateway.this[0]: Refreshing state... [id=nat-02883dcc0730919c0]
  module.vpc.module.vpc.aws_route_table_association.public[2]: Refreshing state... [id=rtbassoc-0249a452e3f9abb36]
  module.vpc.module.vpc.aws_route_table_association.private[2]: Refreshing state... [id=rtbassoc-03c5e67988a5d7e82]
  module.vpc.module.vpc.aws_route_table_association.private[1]: Refreshing state... [id=rtbassoc-0c1c4c526a43cd642]
  module.vpc.module.vpc.aws_route_table_association.private[0]: Refreshing state... [id=rtbassoc-0c6fe768236033ceb]
  module.vpc.module.vpc.aws_route.private_nat_gateway[0]: Refreshing state... [id=r-rtb-0dd52f77a6da2f2b81080289494]
  module.bastion.module.bastion_sg.aws_security_group_rule.egress_rules[0]: Refreshing state... [id=sgrule-4146597370]
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[0]: Refreshing state... [id=sgrule-2752251669]
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[3]: Refreshing state... [id=sgrule-2109081080]
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[1]: Refreshing state... [id=sgrule-1148563241]
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[2]: Refreshing state... [id=sgrule-4076860060]
  module.bastion.aws_instance.bastion: Refreshing state... [id=i-0a0ce9a84e320ee1a]
  
  ------------------------------------------------------------------------
  
  An execution plan has been generated and is shown below.
  Resource actions are indicated with the following symbols:
  +/- create replacement and then destroy
  
  Terraform will perform the following actions:
  
    # module.bastion.aws_instance.bastion must be replaced
  +/- resource "aws_instance" "bastion" {
          ami                          = "ami-08ee2516c7709ea48"
        ~ arn                          = "arn:aws:ec2:us-east-2:555065427312:instance/i-0a0ce9a84e320ee1a" -&gt; (known after apply)
        ~ associate_public_ip_address  = true -&gt; (known after apply)
        ~ availability_zone            = "us-east-2a" -&gt; (known after apply)
        ~ cpu_core_count               = 1 -&gt; (known after apply)
        ~ cpu_threads_per_core         = 1 -&gt; (known after apply)
        - disable_api_termination      = false -&gt; null
        - ebs_optimized                = false -&gt; null
          get_password_data            = false
        - hibernation                  = false -&gt; null
        + host_id                      = (known after apply)
        ~ id                           = "i-0a0ce9a84e320ee1a" -&gt; (known after apply)
        ~ instance_state               = "running" -&gt; (known after apply)
          instance_type                = "t2.micro"
        ~ ipv6_address_count           = 0 -&gt; (known after apply)
        ~ ipv6_addresses               = [] -&gt; (known after apply)
          key_name                     = "project"
        - monitoring                   = false -&gt; null
        + network_interface_id         = (known after apply)
        + outpost_arn                  = (known after apply)
        + password_data                = (known after apply)
        + placement_group              = (known after apply)
        ~ primary_network_interface_id = "eni-06538a1ff826fc7cd" -&gt; (known after apply)
        ~ private_dns                  = "ip-10-0-101-59.us-east-2.compute.internal" -&gt; (known after apply)
        ~ private_ip                   = "10.0.101.59" -&gt; (known after apply)
        ~ public_dns                   = "ec2-3-14-143-30.us-east-2.compute.amazonaws.com" -&gt; (known after apply)
        ~ public_ip                    = "3.14.143.30" -&gt; (known after apply)
        ~ security_groups              = [ # forces replacement
            + "sg-083a3f9ac371028cc",
          ]
          source_dest_check            = true
          subnet_id                    = "subnet-0fd9ca3b8e2220d17"
          tags                         = {
              "Name"        = "edna-devstg-bastion"
              "environment" = "dev/stg"
              "project"     = "eDNA"
              "team"        = "project"
              "terraform"   = "true"
          }
        ~ tenancy                      = "default" -&gt; (known after apply)
        ~ volume_tags                  = {} -&gt; (known after apply)
        ~ vpc_security_group_ids       = [
            - "sg-083a3f9ac371028cc",
          ] -&gt; (known after apply)
  
        - credit_specification {
            - cpu_credits = "standard" -&gt; 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)
          }
  
        ~ metadata_options {
            ~ http_endpoint               = "enabled" -&gt; (known after apply)
            ~ http_put_response_hop_limit = 1 -&gt; (known after apply)
            ~ http_tokens                 = "optional" -&gt; (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 = false -&gt; (known after apply)
            ~ device_name           = "/dev/sda1" -&gt; (known after apply)
            ~ encrypted             = false -&gt; (known after apply)
            ~ iops                  = 100 -&gt; (known after apply)
            + kms_key_id            = (known after apply)
            ~ volume_id             = "vol-0ff291d46afbd5aaa" -&gt; (known after apply)
            ~ volume_size           = 8 -&gt; (known after apply)
            ~ volume_type           = "gp2" -&gt; (known after apply)
          }
      }
  
  Plan: 1 to add, 0 to change, 1 to destroy.
  
  ------------------------------------------------------------------------
  
  Note: You didn't specify an "-out" parameter to save this plan, so Terraform
  can't guarantee that exactly these actions will be performed if
  "terraform apply" is subsequently run.
  
  </code></pre>
  
  <p>I have tried previously to check how <strong>taint</strong> command is working and did this</p>
  
  <p><a href="https://i.stack.imgur.com/o346b.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/o346b.png" alt="enter image description here"></a></p>
  
  <p>but then I tried to delete and recreate the stack completely. And it seems I don't have "tainted" resources because the following output says so.</p>
  
  <pre class="lang-sh prettyprint-override"><code>✦ ➜ terraform state list | xargs -L 1 terraform untaint
  
  Error: Resource instance is not tainted
  
  Resource instance data.aws_availability_zones.all is not currently tainted,
  and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.bastion.aws_instance.bastion is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.bastion.aws_key_pair.ssh_key is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.s3.aws_s3_bucket.project_bucket is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group.this_name_prefix[0] is not
  currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group_rule.egress_rules[0] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[0] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[1] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[2] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance
  module.bastion.module.bastion_sg.aws_security_group_rule.ingress_rules[3] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_eip.nat[0] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_internet_gateway.this[0] is not
  currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_nat_gateway.this[0] is not
  currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route.private_nat_gateway[0] is
  not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route.public_internet_gateway[0]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table.private[0] is not
  currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table.public[0] is not
  currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.private[0]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.private[1]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.private[2]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.public[0]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.public[1]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_route_table_association.public[2]
  is not currently tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.private[0] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.private[1] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.private[2] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.public[0] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.public[1] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_subnet.public[2] is not currently
  tainted, and so it cannot be untainted.
  
  
  Error: Resource instance is not tainted
  
  Resource instance module.vpc.module.vpc.aws_vpc.this[0] is not currently
  tainted, and so it cannot be untainted.
  
  </code></pre>
  
  <p>However I am still getting <strong>bastion</strong> host recreated because it is forced by </p>
  
  <pre><code>~ security_groups              = [ # forces replacement
            + "sg-083a3f9ac371028cc",
          ]
  
  </code></pre>
  
  <h2>This is my structure of modules</h2>
  
  <pre><code>├── config.tf
  ├── env.auto.tfvars
  ├── goodies
  │   └── bastion_ip_address.txt
  ├── main.tf
  ├── modules
  │   ├── bastion
  │   │   ├── main.tf
  │   │   ├── outputs.tf
  │   │   └── variables.tf
  │   ├── cassandra
  │   ├── elasticache
  │   ├── kubernetes
  │   ├── rds
  │   ├── s3
  │   │   └── main.tf
  │   └── vpc
  │       ├── main.tf
  │       ├── outputs.tf
  │       └── variables.tf
  ├── README.md
  └── variables.tf
  </code></pre>
  
  <h2>main.tf (root level)</h2>
  
  <pre><code>module "s3" {
    source = "./modules/s3"
  }
  
  module "vpc" {
    source      = "./modules/vpc"
    team        = var.team
    project     = var.project
    component   = ""
    environment = var.environment
    tags        = module.project_config.tags
  }
  
  module "bastion" {
    source        = "./modules/bastion"
    vpc_id        = module.vpc.vpc_id
    vpc_subnet_id = module.vpc.public_subnets[0]
    instance_type = "t2.micro"
    team          = var.team
    project       = var.project
    component     = ""
    environment   = var.environment
    tags          = module.project_config.tags
  }
  
  </code></pre>
  
  <h2>This is my bastion terraform config modules/bastion/main.tf</h2>
  
  <pre><code>module "bastion_label" {
    source      = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
    namespace   = var.project
    environment = var.environment
    attributes  = [var.component]
    name        = "bastion"
  }
  
  # 
  # Local computed variables
  # 
  # locals {
  #   names = {
  #     bastion_sg = join(module.bastion_label.delimiter, [module.bastion_label.id, "sg"])
  #   }
  # }
  
  # 
  # Define security key
  # 
  resource "aws_key_pair" "ssh_key" {
    key_name   = var.team
    public_key = file(".ssh/${var.team}.pub")
  }
  
  # 
  # Define bastion security group
  # 
  module "bastion_sg" {
    source = "terraform-aws-modules/security-group/aws"
  
    name        = "bastion-sg"
    description = "security group for bastion host"
    vpc_id      = var.vpc_id
  
    ingress_cidr_blocks = ["0.0.0.0/0"]
    ingress_rules       = ["https-443-tcp", "http-80-tcp", "ssh-tcp", "all-icmp"]
    egress_rules        = ["all-all"]
  
    tags = var.tags
  }
  
  #
  # Define bastion ec2 instance
  #
  resource "aws_instance" "bastion" {
    instance_type = var.instance_type
    ami           = "ami-08ee2516c7709ea48"
    key_name      = aws_key_pair.ssh_key.key_name
    subnet_id     = var.vpc_subnet_id
  
    security_groups = [
      module.bastion_sg.this_security_group_id
    ]
  
    connection {
      type        = "ssh"
      user        = "centos"
      private_key = file(".ssh/${var.team}")
      host        = self.public_ip
    }
  
    depends_on = [aws_key_pair.ssh_key]
  
    lifecycle {
      create_before_destroy = true
    }
  
    tags = merge(var.tags, {
      Name = module.bastion_label.id
    })
  }
  
  
  </code></pre>
  
  <h1>What am I doing wrong or have missed?</h1>