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

depends_on with instance replacement not working as expected #16200

Open
bacoboy opened this issue Sep 27, 2017 · 5 comments
Open

depends_on with instance replacement not working as expected #16200

bacoboy opened this issue Sep 27, 2017 · 5 comments

Comments

@bacoboy
Copy link

bacoboy commented Sep 27, 2017

The setup for this problem is I'm trying to figure out how to roll instances in AWS in sequence
using explicit depends_on between resources. In cases where new instances can be created first
using the lifecycle directive create_before_destroy=true, this works just fine. However, for instances
that have an unsharable property (like a fixed IP), the replacement sequence does not work as expected.

This is needed to be able to do things like quorum replacements (consul, etcd, zookeeper, etc) or
DNS servers at fixed ips without resorting to external script hackery when the rest of your infrastructure
is nicely managed in terraform.

Here is the terraform code I used to demonstrate this:

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

# Launch with first image, then swap out second ami and do terraform apply again
# variable "ami_id" { default = "ami-d651b8ac" }
variable "ami_id" { default = "ami-4fffc834" }

variable "cidr" { default = "192.168.0.0/28" }

resource "aws_vpc" "main" {
  cidr_block = "${var.cidr}"
}

resource "aws_subnet" "main" {
  vpc_id     = "${aws_vpc.main.id}"
  cidr_block = "${var.cidr}"
}

resource "aws_instance" "one" {
  ami           = "${var.ami_id}"
  subnet_id     = "${aws_subnet.main.id}"
  instance_type = "t2.micro"
  private_ip    = "${cidrhost(var.cidr, 5)}"
}

resource "aws_instance" "two" {
  ami           = "${var.ami_id}"
  subnet_id     = "${aws_subnet.main.id}"
  instance_type = "t2.micro"
  private_ip    = "${cidrhost(var.cidr, 6)}"
  depends_on = [ "aws_instance.one" ]
}

resource "aws_instance" "three" {
  ami           = "${var.ami_id}"
  subnet_id     = "${aws_subnet.main.id}"
  instance_type = "t2.micro"
  private_ip    = "${cidrhost(var.cidr, 7)}"
  depends_on = [ "aws_instance.two" ]
}

Here I create 3 instances in sequence as described in this dependency graph:

graph

Now the first time I run this, there are no instances so they get created in dependency sequence:

  • create one
  • create two
  • create three
% 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.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_instance.one
      id:                               <computed>
      ami:                              "ami-4fffc834"
      associate_public_ip_address:      <computed>
      availability_zone:                <computed>
      ebs_block_device.#:               <computed>
      ephemeral_block_device.#:         <computed>
      instance_state:                   <computed>
      instance_type:                    "t2.micro"
      ipv6_address_count:               <computed>
      ipv6_addresses.#:                 <computed>
      key_name:                         <computed>
      network_interface.#:              <computed>
      network_interface_id:             <computed>
      placement_group:                  <computed>
      primary_network_interface_id:     <computed>
      private_dns:                      <computed>
      private_ip:                       "192.168.0.5"
      public_dns:                       <computed>
      public_ip:                        <computed>
      root_block_device.#:              <computed>
      security_groups.#:                <computed>
      source_dest_check:                "true"
      subnet_id:                        "${aws_subnet.main.id}"
      tenancy:                          <computed>
      volume_tags.%:                    <computed>
      vpc_security_group_ids.#:         <computed>

  + aws_instance.three
      id:                               <computed>
      ami:                              "ami-4fffc834"
      associate_public_ip_address:      <computed>
      availability_zone:                <computed>
      ebs_block_device.#:               <computed>
      ephemeral_block_device.#:         <computed>
      instance_state:                   <computed>
      instance_type:                    "t2.micro"
      ipv6_address_count:               <computed>
      ipv6_addresses.#:                 <computed>
      key_name:                         <computed>
      network_interface.#:              <computed>
      network_interface_id:             <computed>
      placement_group:                  <computed>
      primary_network_interface_id:     <computed>
      private_dns:                      <computed>
      private_ip:                       "192.168.0.7"
      public_dns:                       <computed>
      public_ip:                        <computed>
      root_block_device.#:              <computed>
      security_groups.#:                <computed>
      source_dest_check:                "true"
      subnet_id:                        "${aws_subnet.main.id}"
      tenancy:                          <computed>
      volume_tags.%:                    <computed>
      vpc_security_group_ids.#:         <computed>

  + aws_instance.two
      id:                               <computed>
      ami:                              "ami-4fffc834"
      associate_public_ip_address:      <computed>
      availability_zone:                <computed>
      ebs_block_device.#:               <computed>
      ephemeral_block_device.#:         <computed>
      instance_state:                   <computed>
      instance_type:                    "t2.micro"
      ipv6_address_count:               <computed>
      ipv6_addresses.#:                 <computed>
      key_name:                         <computed>
      network_interface.#:              <computed>
      network_interface_id:             <computed>
      placement_group:                  <computed>
      primary_network_interface_id:     <computed>
      private_dns:                      <computed>
      private_ip:                       "192.168.0.6"
      public_dns:                       <computed>
      public_ip:                        <computed>
      root_block_device.#:              <computed>
      security_groups.#:                <computed>
      source_dest_check:                "true"
      subnet_id:                        "${aws_subnet.main.id}"
      tenancy:                          <computed>
      volume_tags.%:                    <computed>
      vpc_security_group_ids.#:         <computed>

  + aws_subnet.main
      id:                               <computed>
      assign_ipv6_address_on_creation:  "false"
      availability_zone:                <computed>
      cidr_block:                       "192.168.0.0/28"
      ipv6_cidr_block:                  <computed>
      ipv6_cidr_block_association_id:   <computed>
      map_public_ip_on_launch:          "false"
      vpc_id:                           "${aws_vpc.main.id}"

  + aws_vpc.main
      id:                               <computed>
      assign_generated_ipv6_cidr_block: "false"
      cidr_block:                       "192.168.0.0/28"
      default_network_acl_id:           <computed>
      default_route_table_id:           <computed>
      default_security_group_id:        <computed>
      dhcp_options_id:                  <computed>
      enable_classiclink:               <computed>
      enable_classiclink_dns_support:   <computed>
      enable_dns_hostnames:             <computed>
      enable_dns_support:               "true"
      instance_tenancy:                 <computed>
      ipv6_association_id:              <computed>
      ipv6_cidr_block:                  <computed>
      main_route_table_id:              <computed>


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

The apply run (note the sequence of instance creation):

% terraform apply
aws_vpc.main: Creating...
  assign_generated_ipv6_cidr_block: "" => "false"
  cidr_block:                       "" => "192.168.0.0/28"
  default_network_acl_id:           "" => "<computed>"
  default_route_table_id:           "" => "<computed>"
  default_security_group_id:        "" => "<computed>"
  dhcp_options_id:                  "" => "<computed>"
  enable_classiclink:               "" => "<computed>"
  enable_classiclink_dns_support:   "" => "<computed>"
  enable_dns_hostnames:             "" => "<computed>"
  enable_dns_support:               "" => "true"
  instance_tenancy:                 "" => "<computed>"
  ipv6_association_id:              "" => "<computed>"
  ipv6_cidr_block:                  "" => "<computed>"
  main_route_table_id:              "" => "<computed>"
aws_vpc.main: Creation complete after 2s (ID: vpc-98866be0)
aws_subnet.main: Creating...
  assign_ipv6_address_on_creation: "" => "false"
  availability_zone:               "" => "<computed>"
  cidr_block:                      "" => "192.168.0.0/28"
  ipv6_cidr_block:                 "" => "<computed>"
  ipv6_cidr_block_association_id:  "" => "<computed>"
  map_public_ip_on_launch:         "" => "false"
  vpc_id:                          "" => "vpc-98866be0"
aws_subnet.main: Creation complete after 1s (ID: subnet-7556f811)
aws_instance.one: Creating...
  ami:                          "" => "ami-4fffc834"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.5"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.one: Still creating... (10s elapsed)
aws_instance.one: Still creating... (20s elapsed)
aws_instance.one: Still creating... (30s elapsed)
aws_instance.one: Creation complete after 32s (ID: i-0b3dd5fecf98efc2e)
aws_instance.two: Creating...
  ami:                          "" => "ami-4fffc834"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.6"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.two: Still creating... (10s elapsed)
aws_instance.two: Still creating... (20s elapsed)
aws_instance.two: Creation complete after 22s (ID: i-06d2ce2758747b75d)
aws_instance.three: Creating...
  ami:                          "" => "ami-4fffc834"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.7"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.three: Still creating... (10s elapsed)
aws_instance.three: Still creating... (20s elapsed)
aws_instance.three: Still creating... (30s elapsed)
aws_instance.three: Creation complete after 32s (ID: i-0b944917caaa6a012)

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

OK so everything looks good, but now I have a new image I need to swap out one at a time.

To simulate this I change the ami_id to something else and you see the plan wants
to swap the instances, but delete first since the fixed IP doesn't
allow for lifecycle { create_before_destroy = true } semantics.
It even says destroy and then create replacement which is what I wanted:

% 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.

aws_vpc.main: Refreshing state... (ID: vpc-98866be0)
aws_subnet.main: Refreshing state... (ID: subnet-7556f811)
aws_instance.one: Refreshing state... (ID: i-0b3dd5fecf98efc2e)
aws_instance.two: Refreshing state... (ID: i-06d2ce2758747b75d)
aws_instance.three: Refreshing state... (ID: i-0b944917caaa6a012)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ aws_instance.one (new resource required)
      id:                           "i-0b3dd5fecf98efc2e" => <computed> (forces new resource)
      ami:                          "ami-4fffc834" => "ami-d651b8ac" (forces new resource)
      associate_public_ip_address:  "false" => <computed>
      availability_zone:            "us-east-1c" => <computed>
      ebs_block_device.#:           "0" => <computed>
      ephemeral_block_device.#:     "0" => <computed>
      instance_state:               "running" => <computed>
      instance_type:                "t2.micro" => "t2.micro"
      ipv6_address_count:           "" => <computed>
      ipv6_addresses.#:             "0" => <computed>
      key_name:                     "" => <computed>
      network_interface.#:          "0" => <computed>
      network_interface_id:         "eni-05685712" => <computed>
      placement_group:              "" => <computed>
      primary_network_interface_id: "eni-05685712" => <computed>
      private_dns:                  "ip-192-168-0-5.ec2.internal" => <computed>
      private_ip:                   "192.168.0.5" => "192.168.0.5"
      public_dns:                   "" => <computed>
      public_ip:                    "" => <computed>
      root_block_device.#:          "1" => <computed>
      security_groups.#:            "0" => <computed>
      source_dest_check:            "true" => "true"
      subnet_id:                    "subnet-7556f811" => "subnet-7556f811"
      tenancy:                      "default" => <computed>
      volume_tags.%:                "0" => <computed>
      vpc_security_group_ids.#:     "1" => <computed>

-/+ aws_instance.three (new resource required)
      id:                           "i-0b944917caaa6a012" => <computed> (forces new resource)
      ami:                          "ami-4fffc834" => "ami-d651b8ac" (forces new resource)
      associate_public_ip_address:  "false" => <computed>
      availability_zone:            "us-east-1c" => <computed>
      ebs_block_device.#:           "0" => <computed>
      ephemeral_block_device.#:     "0" => <computed>
      instance_state:               "running" => <computed>
      instance_type:                "t2.micro" => "t2.micro"
      ipv6_address_count:           "" => <computed>
      ipv6_addresses.#:             "0" => <computed>
      key_name:                     "" => <computed>
      network_interface.#:          "0" => <computed>
      network_interface_id:         "eni-d06d52c7" => <computed>
      placement_group:              "" => <computed>
      primary_network_interface_id: "eni-d06d52c7" => <computed>
      private_dns:                  "ip-192-168-0-7.ec2.internal" => <computed>
      private_ip:                   "192.168.0.7" => "192.168.0.7"
      public_dns:                   "" => <computed>
      public_ip:                    "" => <computed>
      root_block_device.#:          "1" => <computed>
      security_groups.#:            "0" => <computed>
      source_dest_check:            "true" => "true"
      subnet_id:                    "subnet-7556f811" => "subnet-7556f811"
      tenancy:                      "default" => <computed>
      volume_tags.%:                "0" => <computed>
      vpc_security_group_ids.#:     "1" => <computed>

-/+ aws_instance.two (new resource required)
      id:                           "i-06d2ce2758747b75d" => <computed> (forces new resource)
      ami:                          "ami-4fffc834" => "ami-d651b8ac" (forces new resource)
      associate_public_ip_address:  "false" => <computed>
      availability_zone:            "us-east-1c" => <computed>
      ebs_block_device.#:           "0" => <computed>
      ephemeral_block_device.#:     "0" => <computed>
      instance_state:               "running" => <computed>
      instance_type:                "t2.micro" => "t2.micro"
      ipv6_address_count:           "" => <computed>
      ipv6_addresses.#:             "0" => <computed>
      key_name:                     "" => <computed>
      network_interface.#:          "0" => <computed>
      network_interface_id:         "eni-d06f50c7" => <computed>
      placement_group:              "" => <computed>
      primary_network_interface_id: "eni-d06f50c7" => <computed>
      private_dns:                  "ip-192-168-0-6.ec2.internal" => <computed>
      private_ip:                   "192.168.0.6" => "192.168.0.6"
      public_dns:                   "" => <computed>
      public_ip:                    "" => <computed>
      root_block_device.#:          "1" => <computed>
      security_groups.#:            "0" => <computed>
      source_dest_check:            "true" => "true"
      subnet_id:                    "subnet-7556f811" => "subnet-7556f811"
      tenancy:                      "default" => <computed>
      volume_tags.%:                "0" => <computed>
      vpc_security_group_ids.#:     "1" => <computed>


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

Now when I run, I expected this sequence:

  • delete three
  • create three
  • delete two
  • create two
  • delete one
  • create one

What I got was:

  • delete three
  • delete two
  • delete one
  • create one
  • create two
  • create three

as you can see here:

% terraform apply
aws_vpc.main: Refreshing state... (ID: vpc-98866be0)
aws_subnet.main: Refreshing state... (ID: subnet-7556f811)
aws_instance.one: Refreshing state... (ID: i-0b3dd5fecf98efc2e)
aws_instance.two: Refreshing state... (ID: i-06d2ce2758747b75d)
aws_instance.three: Refreshing state... (ID: i-0b944917caaa6a012)
aws_instance.three: Destroying... (ID: i-0b944917caaa6a012)
aws_instance.three: Still destroying... (ID: i-0b944917caaa6a012, 10s elapsed)
aws_instance.three: Still destroying... (ID: i-0b944917caaa6a012, 20s elapsed)
aws_instance.three: Still destroying... (ID: i-0b944917caaa6a012, 30s elapsed)
aws_instance.three: Still destroying... (ID: i-0b944917caaa6a012, 40s elapsed)
aws_instance.three: Still destroying... (ID: i-0b944917caaa6a012, 50s elapsed)
aws_instance.three: Destruction complete after 50s
aws_instance.two: Destroying... (ID: i-06d2ce2758747b75d)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 10s elapsed)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 20s elapsed)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 30s elapsed)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 40s elapsed)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 50s elapsed)
aws_instance.two: Still destroying... (ID: i-06d2ce2758747b75d, 1m0s elapsed)
aws_instance.two: Destruction complete after 1m1s
aws_instance.one: Destroying... (ID: i-0b3dd5fecf98efc2e)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 10s elapsed)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 20s elapsed)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 30s elapsed)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 40s elapsed)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 50s elapsed)
aws_instance.one: Still destroying... (ID: i-0b3dd5fecf98efc2e, 1m0s elapsed)
aws_instance.one: Destruction complete after 1m1s
aws_instance.one: Creating...
  ami:                          "" => "ami-d651b8ac"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.5"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.one: Still creating... (10s elapsed)
aws_instance.one: Still creating... (20s elapsed)
aws_instance.one: Still creating... (30s elapsed)
aws_instance.one: Creation complete after 33s (ID: i-079bb48e9e8efc7a2)
aws_instance.two: Creating...
  ami:                          "" => "ami-d651b8ac"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.6"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.two: Still creating... (10s elapsed)
aws_instance.two: Still creating... (20s elapsed)
aws_instance.two: Still creating... (30s elapsed)
aws_instance.two: Creation complete after 32s (ID: i-0784548c393798b7c)
aws_instance.three: Creating...
  ami:                          "" => "ami-d651b8ac"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t2.micro"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "192.168.0.7"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "subnet-7556f811"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.three: Still creating... (10s elapsed)
aws_instance.three: Still creating... (20s elapsed)
aws_instance.three: Still creating... (30s elapsed)
aws_instance.three: Creation complete after 33s (ID: i-076978fcd6a0893be)

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

Other people have brought this up and said things like "I'm sure there is some kind of work-around",
but I've looked and looked and this just doesn't seem to be supported.

Perhaps there is some ambiguity that can be addressed with an explicit block like:

lifecycle {
  create_immediate_after_destroy = true
}

Items which may or may not be related, but smell similar:

@jbardin
Copy link
Member

jbardin commented Sep 27, 2017

Hi @bacoboy,

This is a hard problem to solve. Yes, the fundamental issue here is that Terraform can't re-order the new resources, precisely because of the dependencies you put in the configuration. The new three can't be created, because it depends on the new two, which depends on the new one.

One workaround is obviously to run terraform 3 times, replacing the instances in the order required.

I don't think there's a way to interject some null resources in there to force the order, but it might be worth playing with to see what the graph looks like.

I think the idea of a new lifecycle (e.g. create_immediate_after_destroy or similar) might be the only way to solve this, since there's no way Terraform could resolve the order on it's own.

Another idea would be to have some sort of lifecycle group in the configuration, where one could declare the order of operations for a set of resources.

Thanks for the great example!

@bacoboy
Copy link
Author

bacoboy commented Sep 28, 2017

Some diagrams to help think about it. The dotted line is from the "must delete before create" lifecycle in replace situations. The solid lines are what terraform computes.

Not sure if github will render these inline so will include links...

Create cycle

graph LR
  1c((create one))-->2c((create two))
  2c-->3c((create three))
Loading

The Replace cycle as it currently works when no lifecycle is specified:

graph TB
  3d-->2d
  2d-->1d
  1c-->2c
  2c-->3c
  subgraph one
  1d{destroy one}-.->1c((create one))
  end
  subgraph two
  2d{destroy two}-.->2c((create two))
  end
  subgraph three
  3d{destroy three}-.->3c((create three))
  end
Loading

This flag (if set) would swap out the calculated links between the create steps and link across dependencies more explicitly note the 3rd and 4th link in the code changes:

graph TB
  3d-->2d
  2d-->1d
  3c-->2d
  2c-->1d
  subgraph one
  1d{destroy one}-.->1c((create one))
  end
  subgraph two
  2d{destroy two}-.->2c((create two))
  end
  subgraph three
  3d{destroy three}-.->3c((create three))
  end
Loading

@bacoboy
Copy link
Author

bacoboy commented Mar 6, 2019

Long time passed since I submitted this, but (currently) 0.11.11 still has this behavior.

Trying to sequence 3 "force new resource/tainted) changes.

Graphs of behaviors still follow this previous comment

Will there be a way to handle this in 0.12?

I've tried the null_resource chaining to no avail. The create_immediate_after_destroy signal is the least impactful way of doing this I can think of.

@bacoboy
Copy link
Author

bacoboy commented Mar 11, 2020

@jbardin Been another year so checking in on any progress/thoughts on more specific lifecycle management in TF?

@bacoboy
Copy link
Author

bacoboy commented Oct 28, 2022

Has it really been 5 years?! Would still love to see some movement on this (as it just came up in (different) job - again).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants