Terraform 0.11: Not able to add dynamic security group to aws instance

460 Views Asked by At

In the ec2 instance module I have couple of security groups one from variable and other created in the module. I have a situation where new security groups are to be added in the terraform file which are sourcing from this module.

To be able to concat a new list I want to convert existing format1 into an explicit list which I am not able to do. How can I achieve this?

resource "aws_instance" "instance" {
//...
# (current)format1: Works
vpc_security_group_ids = ["${aws_security_group.secGrp_1.id}", "${var.secGrp_2}"] 

# format2: Doesn't work
vpc_security_group_ids = "${list(aws_security_group.secGrp_1.id, var.secGrp_2)}"

# format3: Works
vpc_security_group_ids = "${list(var.secGrp_2)}"

# format3: Doesn't works
vpc_security_group_ids = "${list(tostring(aws_security_group.secGrp_1.id), var.secGrp_2)}"

Format2 fails with: "vpc_security_group_ids: should be a list". I suspect the secGrp1 id is not being recognized as a string in this representation.

Format4 fails with: "unknown function called: tostring in: ${(list(tostring(aws_security_group.secGrp_1.id), var.secGrp_2))}"

P.S: The Terraform version we are using is 0.11.x

1

There are 1 best solutions below

1
On

Terraform v0.11 is unable to represent partially-unknown lists during expression evaluation. On initial create, aws_security_group.secGrp_1.id will be unknown and therefore passing it to the list function will produce a wholly-unknown value, which isn't valid to use as the value for a list argument.

This is one of the various expression-language-related problems that Terraform v0.12 addressed. In Terraform v0.12 the following expression equivalent to your second one should work:

  vpc_security_group_ids = [
    aws_security_group.secGrp_1.id,
    var.secGrp_2,
  ]

To get your intended result with Terraform v0.11 will require applying this configuration in two stages, so that Terraform can know the value of aws_security_group.secGrp_1.id before evaluating aws_instance.instance:

  1. terraform apply -target=aws_security_group.secGrp_1 to apply only that resource and the other resources it depends on.
  2. Then just terraform apply to apply everything else, including aws_instance.instance.