Terraform: How to manage individual resources when using count

Created on 19 Nov 2015  ·  5Comments  ·  Source: hashicorp/terraform

I'm not sure if this should be an issue or not so excuse me if it's in the wrong place.

I am using the aws_iam_user resource to manage users like this:

resource "aws_iam_user" "admin_users" {
  count = "${length(split(",", var.admin_users))}"
  name = "${element(split(",", var.admin_users), count.index)}"
}

The users are defined as a comma delimited string like this:

variable "admin_users" {
  default = "user1,user2"
}

After I've run "terraform apply" and created the users I now want to remove user1. So I remove user1 from the string so it's like this:

variable "admin_users" {
  default = "user2"
}

When I run "terraform plan" I get this:

The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

~ module.users.aws_iam_group_membership.admin_members
    users.#:          "2" => "1"
    users.2354152789: "user1" => ""
    users.358143215:  "user2" => "user2"

-/+ module.users.aws_iam_user.admin_users
    arn:       "arn:aws:iam::094598394518:user/user1" => "<computed>"
    name:      "user1" => "user2" (forces new resource)
    path:      "/" => "/"
    unique_id: "AIDAIRHPYR3R46Z37JT3A" => "<computed>"

- module.users.aws_iam_user.admin_users.1


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

So not only is user1 being deleted but user2 is being destroyed and created again. How can we reliably manage the individual resources when using count? Is the solution just not to use count? If so then this makes templates less reusable.

core question

Most helpful comment

Was just putting together an example and about to come in and create this same issue when I found this one :smile:

I'll provide the example I put together:

variable "count" {}

resource "template_file" "foo" {
  count = "${var.count}"
  template = "foo.tpl"
  vars { index = "${count.index}" }
}

resource "null_resource" "bar" {
  count = "${var.count}"
  triggers {
    foo = "${element(template_file.foo.*.rendered, count.index)}"
  }
}

And the following shell session:

$> terraform apply -var 'count=1'
…
$> terraform plan --var 'count=2'
Refreshing Terraform state prior to plan...

template_file.foo.0: Refreshing state... (ID: 9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa)
null_resource.bar.0: Refreshing state... (ID: 7248997055001344561)
…

-/+ null_resource.bar.0
    triggers.#:   "1" => "<computed>" (forces new resource)
    triggers.foo: "0\n" => ""

+ null_resource.bar.1
    triggers.#: "" => "<computed>"

+ template_file.foo.1
    rendered:   "" => "<computed>"
    template:   "" => "foo.tpl"
    vars.#:     "" => "1"
    vars.index: "" => "1" 

So all I'm doing is increasing the count and it wants to recreate the first resource. What's somewhat surprising is that decreasing the count from 2 to 1 doesn't want to do the same (i.e., it will only destroy the second resource, leaving the first untouched).

I can see removing things from the middle of a count-ed resource being a little more complex, but I think the UX of terraform would greatly benefit from detecting these changes and giving a minimal plan.

All 5 comments

Was just putting together an example and about to come in and create this same issue when I found this one :smile:

I'll provide the example I put together:

variable "count" {}

resource "template_file" "foo" {
  count = "${var.count}"
  template = "foo.tpl"
  vars { index = "${count.index}" }
}

resource "null_resource" "bar" {
  count = "${var.count}"
  triggers {
    foo = "${element(template_file.foo.*.rendered, count.index)}"
  }
}

And the following shell session:

$> terraform apply -var 'count=1'
…
$> terraform plan --var 'count=2'
Refreshing Terraform state prior to plan...

template_file.foo.0: Refreshing state... (ID: 9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa)
null_resource.bar.0: Refreshing state... (ID: 7248997055001344561)
…

-/+ null_resource.bar.0
    triggers.#:   "1" => "<computed>" (forces new resource)
    triggers.foo: "0\n" => ""

+ null_resource.bar.1
    triggers.#: "" => "<computed>"

+ template_file.foo.1
    rendered:   "" => "<computed>"
    template:   "" => "foo.tpl"
    vars.#:     "" => "1"
    vars.index: "" => "1" 

So all I'm doing is increasing the count and it wants to recreate the first resource. What's somewhat surprising is that decreasing the count from 2 to 1 doesn't want to do the same (i.e., it will only destroy the second resource, leaving the first untouched).

I can see removing things from the middle of a count-ed resource being a little more complex, but I think the UX of terraform would greatly benefit from detecting these changes and giving a minimal plan.

Any updates here? It's a pretty huge problem for us. If I can help push this along in any way, let me know by pointing me in the right direction to fix it.

Actually, perhaps this is a duplicate of https://github.com/hashicorp/terraform/issues/3449?

This is a dup of #3449, thanks @thegedge

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.

Was this page helpful?
0 / 5 - 0 ratings