Terraform: Error: security_groups: should be a list. in AWS_LAUNCH_CONFIGURATION API

Created on 22 Apr 2017  ·  31Comments  ·  Source: hashicorp/terraform

I am on Terraform v0.9.2.

I get error security_groups: should be a list eventhough it is supplied as a list. Seems the issue was addressed with #691 but it is surfacing now for me. I have added my snippets to #691 for reproducing the error.

bug provideaws

Most helpful comment

@catsby I had this problem as well and I agree with @cheburakshu that it is a problem, either with the documentation or the implementation, depending on which one is right.

The documentation you linked to (https://www.terraform.io/docs/configuration/interpolation.html#user-list-variables) says:

User list variables

The syntax is "${var.LIST}". For example, "${var.subnets}" would get the value of the subnets list, as a list.

But it appears that in this case at least we are required to reference a list as ["${var.subnets}"] - that is definitely not clear from the documentation. If it is the correct behavior, perhaps just a fix to those docs is in order?

All 31 comments

Same behavior on aws_auto_scaling_group too.
It will not accept unless explicitly passed over as a list.

Hi @cheburakshu , to better understand the issue & make it easier to reproduce for anyone else would you mind sharing more details? e.g.

  • terraform config you ran (minus any secrets)
  • full output (stdout + stderr) from terraform commands you ran (minus any secrets)
  • debug log from terraform commands you ran (minus any secrets)

Thanks.

@stack72

Please clone this repo -- github.com/cheburakshu/terrakube.
The config file has no secrets. Uses AWS RSA Keys (a config param). run.sh is the entry point for the modules.
Now this fails on autoscaling_group tag.
I have same issue on these modules - aws_launch_configuration [security_groups], aws_autoscaling_group [vpc_zone_identifier, tag], aws_instance [vpc_security_group_ids].
Please let me know if you need more info.
The way I moved on with the other error is listed in the below snippet.

I am on Terrform v0.9.2

module "launch_configuration" {
  source = "./modules/aws_launch_configuration"
  name = "${module.cluster.asg_name}"
  image_id = "${var.images[var.region]}"
  iam_instance_profile = "${module.cluster.id}"
  instance_type = "${var.size["minion"]}"
  key_name = "${module.key_pair.key_name}"
# There is a bug. This is not allowing me to send a list.
  security_groups = ["${module.minion_security_group.id}"]
  associate_public_ip_address = "${var.associate_public_ip_address}"
  spot_price = "${var.spot_price}"
  user_data = ""
}

Module:

variable "name" {}
variable "image_id" {}
variable "iam_instance_profile" {}
variable "instance_type" {}
variable "key_name" {}
variable "security_groups" {type="list"}
variable "associate_public_ip_address" {}
variable "spot_price" {}
variable "user_data" {}

resource "aws_launch_configuration" "aws_launch_configuration" {
  name = "${var.name}"
  image_id = "${var.image_id}"
  iam_instance_profile = "${var.iam_instance_profile}"
  instance_type = "${var.instance_type}"
  key_name = "${var.key_name}"
  security_groups = "${var.security_groups}"
  associate_public_ip_address = "${var.associate_public_ip_address}"
  spot_price = "${var.spot_price}"
  user_data = "${var.user_data}"
}

Output:

1 error(s) occurred:

* module.launch_configuration.aws_launch_configuration.aws_launch_configuration: security_groups: should be a list

Change security groups as a list, explicitly in module:

variable "name" {}
variable "image_id" {}
variable "iam_instance_profile" {}
variable "instance_type" {}
variable "key_name" {}
variable "security_groups" {type="list"}
variable "associate_public_ip_address" {}
variable "spot_price" {}
variable "user_data" {}

resource "aws_launch_configuration" "aws_launch_configuration" {
  name = "${var.name}"
  image_id = "${var.image_id}"
  iam_instance_profile = "${var.iam_instance_profile}"
  instance_type = "${var.instance_type}"
  key_name = "${var.key_name}"
# Change as explicit list
  security_groups = ["${var.security_groups}"]
  associate_public_ip_address = "${var.associate_public_ip_address}"
  spot_price = "${var.spot_price}"
  user_data = "${var.user_data}"
}

And it works!

Get: file:///home/sud/cloud/projects/terrakube/modules/aws_launch_configuration
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.

Hey @cheburakshu – the second example is how you are required to reference lists

example: something = ["${var.LIST}"]

@catsby
I don't think your answer is accurate. I am using a module with a variable defined as a list.
The calling .tf can pass a simple list or a list of maps. Refer below for dhcp where it accepts. Many such examples I have where the module fields will not accept list or list of maps. The behavior is inconsistent.

See the example below - This works. Note domain_name_servers is a list.

variable "domain_name" {}
variable "domain_name_servers" {type="list"}
variable "tags" {type="map"}

resource "aws_vpc_dhcp_options" "aws_vpc_dhcp_options" {
  domain_name = "${var.domain_name}"
  domain_name_servers = "${var.domain_name_servers}"
  tags = "${var.tags}"
}

```
variable "security_groups" {type="list"}
...
security_groups = "${var.security_groups}" ERROR
...

This is what is getting passed -

  security_groups = ["${module.minion_security_group.id}"]

@catsby Can this be re-opened. I am not setting a wrong value here. Need help. You can see the code here- github.com/cheburakshu/terrakube

Hey @cheburakshu if you can extract from your example repo a minimal configuration ( a default map value, with something like aws_instance) that demonstrates this issue, I can reopen and investigate. I'm afraid that downloading your repository, which appears to be a work in progress or at least a repository that is not solely created for demonstrating this issue, and digging into your modules is beyond the support I can provide at this time. You may have more luck on our mailing list or over at Stack Overflow.

I sincerely want to help, but I need a more narrow, specific example to be provided.

@catsby I had this problem as well and I agree with @cheburakshu that it is a problem, either with the documentation or the implementation, depending on which one is right.

The documentation you linked to (https://www.terraform.io/docs/configuration/interpolation.html#user-list-variables) says:

User list variables

The syntax is "${var.LIST}". For example, "${var.subnets}" would get the value of the subnets list, as a list.

But it appears that in this case at least we are required to reference a list as ["${var.subnets}"] - that is definitely not clear from the documentation. If it is the correct behavior, perhaps just a fix to those docs is in order?

On further consideration, I think the docs are right and the behavior is wrong. The way we apparently need to surround some list interpolations with square brackets would hide real problems in case the variable passed into the module mistakenly is not a list (i.e. it would convert a string variable into a list of length one rather than giving an error).

Not just lists, if you use auto scaling groups or ebs in modules, you
cannot pass list of maps, lists too.

On Tue, May 30, 2017 at 10:43 AM, Joshua C. Randall <
[email protected]> wrote:

On further consideration, I think the docs are right and the behavior is
wrong. The way we apparently need to surround some list interpolations with
square brackets would hide real problems in case the variable passed into
the module mistakenly is not a list (i.e. it would convert a string
variable into a list of length one rather than giving an error).


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/hashicorp/terraform/issues/13869#issuecomment-304937529,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AaEF0prEfEbAflneHy11Ol4B-SUcwFj-ks5r_Ec3gaJpZM4NFMSY
.

I have just experienced the same issue and agree with @jrandall 's previous 2 comments. Moreover, the issue does not appear when the initial list is created in place, without any variables.

Using: terraform v0.10.2

@catsby I've created a minimal working example repo: https://github.com/rszalski/terraform_list_var_inconsistency I hope it's minimal enough for you to consider reopening and investigating.

This is at the very least a documentation issue and, I agree, if the documentation were updated to match the only thing that works (e.g. param = [ "${var.VARNAME}" ]), it's likely to paper over potential problems, so I'd rather see the implementation fixed. @jrandall @rszalski are on the right path, and issue should be re-opened.

Problem occurs with Terraform v0.10.3 as well.

+1

this problem makes using modules stupid, coupled with issue for just-in-time count expansion: https://github.com/hashicorp/terraform/issues/1497#issuecomment-105874601

I can confirm being befuddled for several minutes by this bug.

just got this confusing error too. the right way to reference a variable is ["${var.listvariable}"] but the documentation says "${var.listvariable}".

this is a bug and should be reopened. my list variable inside a module works without brackets unless the list that's passed in contains a variable, then i have to put brackets around the reference in the module. weird stuff.

I just faced this too. This is definitely confusing and I believe the issue should be reopened.

+1 this is a definite bug seemingly when passing lists into modules.

Simple example:
security_groups = ["sg-123456"] - Works

security_groups = ["${data.terraform_remote_state.root_module.prod-web-sg-id}"] - Complains security_groups is not a list

I also tried a couple of things like calling trimspace() on the interpolated variable to see if that would resolve some kind of typing mismatch, but nope. Something deeper going on that's not self-evident. I disagree that the module definition should be a list to which a string value is passed - not a good workaround and horrible if you have existing module instantiations.

It's trivial to reproduce this as @petewilcock has shown - you'd expect "sg-123456" to be equivalent to "${var.sg}" if var.sg is equal to "sg-123456". It's a one-line terraform plan, what other repo steps are needed?

@catsby Unfortunately this is still an issue. The docs say this:

User list variables

The syntax is "${var.LIST}". For example, "${var.subnets}" would get the value of the subnets list, as a list. You can also return list elements by index: ${var.subnets[idx]}.

It would be great if this were true, but it's not ☹️. If you follow the docs, your code will break. Assuming that subnets is a list, "${var.subnets}" (as mentioned in the docs) will cause an error if you pass it to a variable expecting a list. However, unintuitively, passing ["${var.subnets}"] will work. This correct syntax is not mentioned in the docs.

This can be demonstrated in the minimal repro that @rszalski kindly took the time to put together last August. Here's the important file (it's only 7 lines long).

Since the docs don't match the behavior, there are two possible resolutions here:

  1. Update the docs to match current behavior
  2. Update the behavior to match the docs

I would strongly prefer the former, but if you guys choose the latter, at least your intent will be clear and this inconsistency could still be navigated by reading the docs.

In the meantime, could you please reopen this, add tags core and documentation, and remove tag provider/aws? AWS isn't the only provider with a module that accepts a key of type list. This is an HCL and/or docs issue. Thank you!

Sorry for tagging you, but I just want this to be solved before 1.0 so Terraform is the best it can be ❤️

After I met with this bug, I consciously moved away from writing modules since they are very brittle in behavior (due to parsing of list, list of maps etc) when compared to the resources themselves.

Another major missing feature, though un-related to my original filing of this bug report, is the inability of modules to be used for creating multiple resources. The explosion operation '*', works with resources like a charm and the hope for it to be available in modules is just a distant dream.

Anyway, hope this gets fixed.

I faced this issue too... cannot pass type = "list" in the modules... I like the whole modules, how they work.. these little things need to be fixed for better reusability.

@catsby why have typed variables if the type isn't respected.
https://www.terraform.io/docs/configuration/interpolation.html#user-list-variables

app/alb.tf

module "alb" {
  source = "../alb"

  alb_name = "live-alb"
  alb_subnets = [
    "${aws_subnet.public_subnet.id}",
    "${aws_subnet.public_alternate_subnet.id}"
  ]
  alb_security_groups = [
    "${aws_security_group.internet_access.id}",
    "${aws_security_group.alb_sg.id}"
  ]
}

module alb/alb.tf

variable "alb_subnets" {
  type = "list"
  description = "List of subnets the ALB is connected to"
}

// ALB and associated resources
resource "aws_alb" "alb"
{
  name = "${var.alb_name}"
  internal        = false
  idle_timeout    = 600
  subnets         = "${var.alb_subnets}"
  security_groups = "${var.alb_security_groups}"

  tags = "${var.alb_tags}"
}

Error: module.alb.aws_alb.alb: security_groups: should be a list
Error: module.alb.aws_alb.alb: subnets: should be a list

I also just hit this issue again.

I submitted a PR to describe the current behavior in the docs in lieu of a bugfix.

While I'm here, I'd also like to once again bring attention to the minimal repro that @rszalski kindly took the time to put together last August. Here's the key file in its entirety:

resource "aws_instance" "list-example-ec2" {
  ami                       = "ami-d7b9a2b1"
  instance_type             = "t2.nano"
  vpc_security_group_ids    = "${var.security_group_ids}"
  # However the following works (notice the surrounding square brackets)
  # vpc_security_group_ids    = ["${var.security_group_ids}"]
}

Here is a link to the full repo: https://github.com/rszalski/terraform_list_var_inconsistency

Looks like a fix for this issue is in the works: https://github.com/hashicorp/terraform/pull/18062#issuecomment-390497565

I'm glad they're doing a real fix, although I'm also glad that your PR turned up more information on what's going on. ;)

My devious plan worked perfectly :)

Workaround:
Its not "${var.LIST}". use ["${var.LIST}"] (notice the extra square braces that the official documentation does not mention)

I can't believe the number of really obvious issues with terraform that have been declared not to be issues. This is like the 5th problem I've run into that was misunderstood by the hashicorp team and determined (incorrectly) to be user error for over a year.

The symptoms are that the type is a list and the expected type is a list, but terraform simply states 'should be a list' and does not mention what type was actually passed. When a variable of incorrect type is actually passed, the incorrect type is stated. for example ', got string'

Also why have the 11.x docs not been updated since this issue was reported, verified (and even fixed in .12)?

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