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

Terraform maps - Destroys and creates additional resources based on the alphabetical order of first letter in param name #14477

Closed
kntait opened this issue May 15, 2017 · 5 comments

Comments

@kntait
Copy link

kntait commented May 15, 2017

Hi there,

Terraform Version

0.9.5

Affected Resource(s)

Affects multiple AWS resources that use maps.

Terraform Configuration Files

main.tf
// Route53 

resource "aws_route53_zone" "main" {
  name   = "${var.zone_name}"
  vpc_id = "${aws_vpc.mod.id}"
  count   = "${lookup(map(var.create_default_zone, 1), "true", 0)}"  
}

resource "aws_route53_record" "records" {
  zone_id = "${aws_route53_zone.main.zone_id}"
  name    = "${element(values(var.record_name), count.index )}"
  type    = "${element(values(var.record_type), count.index )}"
  ttl     = "${element(values(var.record_ttl), count.index )}"
  count   = "${length(keys(var.record_name)) * lookup(map(var.enable_zone_records, 1), "true", 0) * lookup(map(var.create_default_zone, 1), "true", 0)}"
  records = ["${element(values(var.record_value), count.index )}",]
}

terraform.tfvars
// Default zone
create_default_zone = "true"
zone_name = "sbx.mydomain.com"
terraform.tf.vars

// Zone records
enable_zone_records = "true"
record_name =  {
  "b"    = "b"
  "a"    = "a"
}
record_type = {
  "b"    = "A"
  "a"    = "A"
}
record_ttl  = {
  "b"    = "30"
  "a"    = "30"
}
record_value = {
  "b"    = "10.0.0.1"
  "a"    = "10.0.0.2"
}

variables.tf
variable "create_default_zone" {}
variable "zone_name" {}
variable "enable_zone_records" {}
variable "record_name" { type = "map" }
variable "record_type" { type = "map" }
variable "record_ttl" { type = "map" }
variable "record_value" { type = "map" }

main.tf 
create_default_zone = "${var.create_default_zone}"
  zone_name = "${var.zone_name}"
  enable_zone_records = "${var.enable_zone_records}"
  record_name = "${var.record_name}"
  record_type = "${var.record_type}"
  record_ttl = "${var.record_ttl}"
  record_value = "${var.record_value}"

Issue

If record "a" is created after record "b" then record "b" should not be re-created. This appears to be due to Terraform maps using the alphabet for ordering.

e.g

record_value = {
"b" = "10.0.0.1" - Terraform resource name: aws_route53_record.record_value.0
}

If you add another parameter:
record_value = {
"b" = "10.0.0.1" Terraform resource name: aws_route53_record.record_value.1
"a" = "10.0.0.2" Terraform resource name: aws_route53_record.record_value.0
}

When "a" is added it now has the resource name aws_route53_record.record_value.0 due to a coming before b in the alphabet. So resource b is then deleted and created with resource name aws_route53_record.record_value.1

Is it possible to fix this issue? This is an issue especially if something is relying on a resource that is re-created.

@egarbi
Copy link
Contributor

egarbi commented Jul 28, 2017

Im using this inside an ALB module to add rules under the listener of the ALB
forwarding request based on path-pattern
first run:

// path-pattern - target-group
variable service_map {
  default = {
    "/v1/receive/algo" = "pepe"
  }
}

Everything went ok, now in my second run.
I added:

variable service_map {
  default = {
    "/v1/receive/algo" = "pepe"
    "/v1/customers*" = "juan"
  }
}

as "/v1/customers*" is now the first element of the list (keys(services_map)).
plan is trying to create not only the second target-group but also recreate the first one as well, not good.
It would be great to have the behaviour of 'keys' function to choose whether if I wanted sorted or not

@jmeisner3
Copy link

jmeisner3 commented Oct 18, 2017

Not sure what the roadmap is here, but would love to see terraform resources have the concept of count_map which exposes count.key or something along those lines in addition to count which currently exposes count.index

Primary difference being, it accepts a map as the input, and that when the resulting tfstate is created it will use the key from the map, instead of a 0 based index to store the information about a resource.

This way as keys come and go from a map, you don't have to worry about the order of keys() causing resources to be re-created un-intentionally.

@bjcone
Copy link

bjcone commented Feb 20, 2018

I ran into this today, fortunately in a testing environment. At the very least it would be nice if this was explicitly articulated in the variable documentation for maps.

Terraform version 0.11.3.

Using a map variable to deploy a series of docker containers and configuration variables. I attempted to add a second container configuration to the deploy which happened to be keyed alphabetically earlier than my original. When planning, terraform was attempting to create a duplicate of my original as it was now the second index in the map.

@apparentlymart
Copy link
Contributor

Hi all! Sorry for the long silence here. I missed this issue before.

This seems like the same thing being discussed in #17179, where I posted earlier our current thinking about how to address this. It's actually very similar to what @jmeisner3 suggested here, albeit with some different attribute/reference names.

As noted over there, we're planning to do this once we've completed some prerequisite work on how Terraform thinks about configuration in general. That work is the current focus for the Terraform Team at HashiCorp and will be included in a future release. I'm not sure yet if the proposed for_each attribute will be completed in time to land concurrently with the other changes, but if not then it hopefully won't be too long afterwards.

I'm going to close this issue just to consolidate the discussion over in #17179. Thanks for opening this issue, and sorry again that I missed it while posting updates.

@ghost
Copy link

ghost commented Apr 4, 2020

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.

@ghost ghost locked and limited conversation to collaborators Apr 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants