Thomas S
Thomas S

Reputation: 13

Terraform for loop resulting in unexpected results when using 'flatten' and 'element' functions

I am trying to parse an array into two arrays by every other element.

example: ["thomas1", "thomas2", "thomas3", "thomas4", "thomas5"] splits into two new arrays: ["thomas1", "thomas3", "thomas5"] and ["thomas2", "thomas4"]

There may be better ways to do this but in Terraform when I use the following code I get a very strange result for my second new array. I am completely scratching my head how that is possible.

locals {
  hostnames = ["thomas1", "thomas2", "thomas3", "thomas4", "thomas5"]
  clusterA_range = range(0,length(local.hostnames),2)
  clusterB_range = range(1,length(local.hostnames),2)
  clusterA = flatten ( [ for i in local.clusterA_range : element(local.hostnames,(element(local.clusterA_range,i))) ] )
  clusterB = flatten ( [ for x in local.clusterB_range : element(local.hostnames,(element(local.clusterB_range,x))) ] )
}

output "hostnames" {
  value = local.hostnames
}
output "clusterA" {
  value = local.clusterA
}
output "clusterB" {
  value = local.clusterB
}
output "clusterA_range" {
  value = local.clusterA_range
}
output "clusterB_range" {
  value = local.clusterB_range
}

which results in:

$ terraform apply

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

Terraform will perform the following actions:

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes


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

Outputs:

clusterA = [
  "thomas1",
  "thomas5",
  "thomas3",
]
clusterA_range = [
  0,
  2,
  4,
]
clusterB = [
  "thomas4",
  "thomas4",
]
clusterB_range = [
  1,
  3,
]
hostnames = [
  "thomas1",
  "thomas2",
  "thomas3",
  "thomas4",
  "thomas5",
]

Why is clusterB ["thomas4","thomas4"]?

Terraform version v0.13.0-dev

Upvotes: 1

Views: 127

Answers (1)

Marcin
Marcin

Reputation: 238299

This happens because you are iterating over values of your ranges, and then using these values to select range values again. If you want to keep your structure, you have to iterate over indices in the ranges:

locals {
  hostnames = ["thomas1", "thomas2", "thomas3", "thomas4", "thomas5"]
  
  clusterA_range = range(0,length(local.hostnames), 2)
  clusterB_range = range(1,length(local.hostnames), 2)
  
  clusterA = flatten ( [ 
      for idxA, i in local.clusterA_range : 
          element(local.hostnames,(element(local.clusterA_range, idxA))) ] )
 
  clusterB = flatten ( 
        [ for idxB, x in local.clusterB_range : 
        element(local.hostnames,(element(local.clusterB_range, idxB))) ] )
}

But, for your particular example, you can simplify your selection:

  clusterA = [for  i in local.clusterA_range :  element(local.hostnames, i) ]
  
  clusterB = [ for x in local.clusterB_range :  element(local.hostnames, x) ]

Upvotes: 1

Related Questions