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

Unable to express list of maps as a literal in variables #7142

Closed
phinze opened this issue Jun 12, 2016 · 15 comments · Fixed by #7582
Closed

Unable to express list of maps as a literal in variables #7142

phinze opened this issue Jun 12, 2016 · 15 comments · Fixed by #7582

Comments

@phinze
Copy link
Contributor

phinze commented Jun 12, 2016

Perhaps this one will be a wontfix for 0.7.0, but I wanted to get it recorded.

Terraform Version

master / 2127466

Affected Resource(s)

core

Terraform Configuration Files

variable "sgtags" {
  type = "list"
  default = [
    {zone = "a"},
    {zone = "b"},
    {zone = "c"},
  ]
}

resource "aws_security_group" {
  count = 3
  tags = "${var.sgtags[count.index]}"
}

Steps to Reproduce

  1. terraform apply

Expected Behavior

3 SGs each with a zone tag.

Actual Behavior

Error loading config: Error parsing /path/to/main.tf: At 4:5: unexpected token while parsing list: LBRACE
@phinze phinze changed the title Unable to express list of maps as a literal Unable to express list of maps as a literal in variables Jun 12, 2016
@phinze
Copy link
Contributor Author

phinze commented Jun 12, 2016

Worth noting that a list of maps can be expressed in both module and resource declarations by repeating blocks.

Examples:

module "foo" {
  source = "./foo"
  listofmaps {
    foo = 1
  }
  listofmaps {
    bar = 2
  }
}
resource "aws_instance" "foo" {
  ebs_block_device {
    device = "/dev/xvda"
    # ...
  }
  ebs_block_device {
    # ...
    device = "/dev/xvdb"
  }
}

@phinze
Copy link
Contributor Author

phinze commented Jun 12, 2016

Related a bit to #7030

@oillio
Copy link

oillio commented Jun 13, 2016

Also duplicate of #7032?

Have you verified that setting tags from a list of maps variable like this works?
I tried to do something similar with aws_elastic_beanstalk_environment.setting with no luck: https://groups.google.com/d/msg/terraform-tool/-42XvH2bbRk/6qrJ8K9hAwAJ

I got an error when I tried: aws_elastic_beanstalk_environment.myEnv: gob: type not registered for interface: map[string]ast.Variable

phinze added a commit to hashicorp/hcl that referenced this issue Jul 6, 2016
a.k.a lists of maps

Implementation was pretty straightforward - I had to tweak the `needsComma`
handling since it was stuck inside literal parsing. It happens out front
now. I also promoted the `assign_deep.hcl` parser test to a decoder
test that passes, since it was testing for an error to occur but now it
works! :)

Refs hashicorp/terraform#7142
phinze added a commit to hashicorp/hcl that referenced this issue Jul 6, 2016
a.k.a lists of maps

Implementation was pretty straightforward - I had to tweak the `needsComma`
handling since it was stuck inside literal parsing. It happens out front
now. I also promoted the `assign_deep.hcl` parser test to a decoder
test that passes, since it was testing for an error to occur but now it
works! :)

Additionally we make ObjectLists support being comma-delimited, which
enables maps to defined inline like `{one = 1, two = 2}`.

Refs hashicorp/terraform#7142
phinze added a commit to hashicorp/hcl that referenced this issue Jul 6, 2016
a.k.a lists of maps

Implementation was pretty straightforward - I had to tweak the `needsComma`
handling since it was stuck inside literal parsing. It happens out front
now. I also promoted the `assign_deep.hcl` parser test to a decoder
test that passes, since it was testing for an error to occur but now it
works! :)

Additionally we make ObjectLists support being comma-delimited, which
enables maps to defined inline like `{one = 1, two = 2}`.

Refs hashicorp/terraform#7142
phinze added a commit that referenced this issue Jul 11, 2016
@joelhandwell
Copy link
Contributor

joelhandwell commented Mar 11, 2017

@glenjamin
Copy link
Contributor

This is marked as closed, but I can't seem to figure out what the actual syntax is. This seems to produce only a single map:

variable "list_of_maps" {
    default {
        id = "747381f4"
        key_permissions = ["get"]
        secret_permissions = ["get"]
    }
    default {
        id = "c411a1534b6e"
        key_permissions = ["get"]
        secret_permissions = ["get"]
    }
}

@jamiel
Copy link

jamiel commented May 10, 2017

Syntax is:

variable "list_of_maps" {
   type = "list"
   default = [
      {
          field = "value"
      },
      {
          field = "value"
      }
   ]
}

@joestump
Copy link

@phinze in your example, how would you declare listofmaps in the module? Also, what happens if you only declare one listofmaps? I looked at your hcl PR and it wasn't 100% clear.

My hope is I can do this:

variable "listofmaps" { type = "list" }

module "foo" {
  # This would end up as ${var.listofmaps.0}
  listofmaps {
    bar = "baz"
  }
}

@phinze
Copy link
Contributor Author

phinze commented Jul 19, 2017

@joestump yep! the variable inside the module will just be "list" as that's the top-level type

@gazoakley
Copy link
Contributor

gazoakley commented Jul 24, 2017

For anyone else trying to figure out how to access an attribute of a specific map, try:

"${lookup(var.var_name[index], "attribute_name")}"

Replacing var_name, index and attribute_name as appropriate

@ericlagergren
Copy link

ericlagergren commented Aug 24, 2017

@phinze I'm unable to get your example working. Using Terraform 0.10.2:

0:0 /tmp/a $ tree
.
├── a.tf
└── b
    └── b.tf

1 directory, 2 files
0:0 /tmp/a $ cat a.tf
provider "aws" {
  region = "us-west-2"
}

module "b" {
  source = "b/"

  list_of_maps {
    name = "name1"
  }

  list_of_maps {
    name = "name2"
  }

  list_of_maps {
    name = "name3"
  }
}
0:0 /tmp/a $ cat b/b.tf
variable "list_of_maps" {
  type = "list"
}

resource "aws_ecs_cluster" "c" {
  count = "${length(var.list_of_maps)}"
  name  = "${lookup(element(var.list_of_maps, count.index), "name")}"
}
0:0 /tmp/a $ terraform plan
1 error(s) occurred:

* module.b.var.list_of_maps: variable list_of_maps in module b should be type list, got map

Yet if I change list_of_maps to be map, I get

Error asking for user input: 1 error(s) occurred:

* module.b.var.list_of_maps: variable list_of_maps in module b should be type map, got list

@phinze
Copy link
Contributor Author

phinze commented Aug 24, 2017

Hi @ericlagergren - that looks correct from here! I'd recommend posting your repro as a fresh issue and referencing back to this one.

@agalazis
Copy link

agalazis commented Oct 30, 2017

the above is not a solution when you want to concatenate a list of maps to another (the one is declared inline and the other from a variable) maybe iterating though the provided would...

@jakubgs
Copy link

jakubgs commented Sep 7, 2018

I think this is still an issue. I really don't see a way of generating a list of maps from a list.
For example:

locals {
  ports = [22, 80, 443]
}

resource "digitalocean_firewall" "host" {
  name        = "some_name"
  droplet_ids = ["${digitalocean_droplet.host.*.id}"]
  inbound_rule = [
    {
      protocol   = "tcp"
      port_range = "${local.open_ports.*}"
    }
  ]
}

I don't see how currently this is possible.

@ghost
Copy link

ghost commented Feb 20, 2019

Could it work if instead of llimited HCL templates we would use a json template?

@ghost
Copy link

ghost commented Mar 29, 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 Mar 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants