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 pass mapping to module #1336

Closed
jamestoyer opened this Issue Mar 30, 2015 · 33 comments

Comments

Projects
None yet
@jamestoyer
Copy link

jamestoyer commented Mar 30, 2015

I'm working with AWS VPCs and I created a module for each region to set up a VPC. In the variables to the module I define a mapping of subnet addresses to availability zones, like so

variable "subnet_addresses" {
  default {
    a = "10.0.0.0/20"
    b = "10.0.16.0/20"
    d = "10.0.48.0/20"
    e = "10.0.64.0/20"
  }
}

I then go ahead and reference this mapping, no problem, to set up the VPC. However, if I try to override this mapping in a file referencing this, I get an error, saying a value in the mapping is not set. Here is an example (a full example is on this gist)

variable "vpc_subnet_addresses" {
  default = {
    a = "10.255.0.0/20"
    b = "10.255.16.0/20"
    d = "10.255.48.0/20"
    e = "10.255.64.0/20"
  }
}

module "new_vpc" {
  source = "my_vpc_module"

  subnet_addresses = "${var.vpc_subnet_addresses}"
}

The error I get is

Error running plan: lookup: lookup in 'vpc_subnet_addresses' failed to find 'e' in:

${lookup(var.subnet_addresses, "e")}

Maybe I'm missing something, I'm just not sure what

@koliyo

This comment has been minimized.

Copy link

koliyo commented May 28, 2015

Same problem here, trying to use the consul module, which only has ami:s defined for us regions. I'm providing an overide mapping like this

variable "consul_ami" {
  default = {
    eu-west-1 = "ami-62a10115"
  }
}

module "consul" {
    source = "github.com/hashicorp/consul/terraform/aws"

    key_name = "${var.consul_key_name}"
    key_path = "${var.consul_key_path}"
    region = "${var.region}" /* this is "eu-west-1" */
    ami = "${var.consul_ami}"
    servers = "3"
}

and I get a very similar error:

* lookup: lookup in 'consul_ami' failed to find 'eu-west-1' in:

${lookup(var.ami, var.region)}
@koliyo

This comment has been minimized.

Copy link

koliyo commented May 28, 2015

Ok, I see in the documentation that this is currently not supported. However, this is very limiting!

What I did to overcome this was to fork the entire consul project, patch the modul variable configuration, and source this forked repository in mu module instantiation.

Please tell me if there is an easier way of working around this problem until map variables are supported in modules.

@dalehamel

This comment has been minimized.

Copy link

dalehamel commented Jul 8, 2015

@phinze @catsby @mitchellh since it seems like only being able to pass strings to modules is a fundamental limitation of terraform's HCL, what are your thoughts on loading a map from a string?

This is currently allowed for lists using syntax like:

["${split(delim, str)}"]

What if another function were added to load maps from, say, JSON strings:

{"${json(str)}"}

Our use case for this is we want to have a module that wraps bringing up chef instances to keep our code DRY. For this, we need to be able to specify attributes to that chef instance, which is a map. There's no way currently to pass this as a variable, so this is impossible and we have to copy a bunch of code.

cc @thegedge

@dalehamel

This comment has been minimized.

Copy link

dalehamel commented Jul 14, 2015

fwiw @jamestoyer @Kolis we have the same problem and worked around this issue as described in #2704, this doesn't solve the problem of not being able to pass maps, but it allows you to fake a map.

The way it works is it uses the index function (not explicitly needed, we faked the index function using 'replace's regex capabilites, but index makes it much, much nicer which is why we made the PR).

The keys and values for the map are serialized into CSV strings that constitute parallel arrays. You find the index of your key using the 'index' function we wrote, and take that integer index against the values.

It's crude, and only supports flat maps, but it gets the job done.

Hope this helps!

@jasonkuhrt

This comment has been minimized.

Copy link

jasonkuhrt commented Oct 2, 2015

For the value of another data point I'll say this is a major limitation from my experience so far (few weeks). I would say modules are incomplete without this feature (and a few others).

@AVVS

This comment has been minimized.

Copy link

AVVS commented Oct 22, 2015

any ETA to address this?

@jordiclariana

This comment has been minimized.

Copy link

jordiclariana commented Oct 28, 2015

I just have run into this problem. A solution will be really appreciated.
Is this at least under consideration?

@phinze

This comment has been minimized.

Copy link
Member

phinze commented Oct 28, 2015

It's definitely something we'd like to get fixed - the delay comes from the difficulty in implementation. It will require a lot of significant work in the config type system to support this. We'll definitely do it - just need to find the time to get it done!

@barbarello

This comment has been minimized.

Copy link

barbarello commented Nov 2, 2015

+1
ran into it as well

@conorgil

This comment has been minimized.

Copy link

conorgil commented Nov 19, 2015

+1
Just ran into this same problem.

@runtheops

This comment has been minimized.

Copy link

runtheops commented Dec 7, 2015

+1
same thing here

@tylerFowler

This comment has been minimized.

Copy link

tylerFowler commented Jan 22, 2016

+1 this would be very handy for things like AMI maps (which I like to keep at the top level of the project), would also be nice from a cleanliness standpoint on being able to write stuff like credentials to maps to keep things logically separated.

@przemyslaw-iwanek

This comment has been minimized.

Copy link

przemyslaw-iwanek commented Feb 22, 2016

+1 this will be very helpful for us.

@tehmaspc

This comment has been minimized.

Copy link

tehmaspc commented Feb 24, 2016

+1

2 similar comments
@Shruti29

This comment has been minimized.

Copy link

Shruti29 commented Mar 7, 2016

+1

@humantorpedo

This comment has been minimized.

Copy link

humantorpedo commented Mar 10, 2016

+1

@jzohrab

This comment has been minimized.

Copy link
Contributor

jzohrab commented Mar 10, 2016

+1. We're currently symlinking a lot to get around this.

@eedwardsdisco

This comment has been minimized.

Copy link

eedwardsdisco commented Mar 25, 2016

+1 WHY IS THIS NOT A FEATURE??

@dtx

This comment has been minimized.

Copy link

dtx commented Mar 30, 2016

+1

1 similar comment
@prozach

This comment has been minimized.

Copy link

prozach commented Apr 4, 2016

+1

@deconduino

This comment has been minimized.

Copy link

deconduino commented Apr 7, 2016

+1. We pass a large number of standard/repeated variables to different modules so it would make a huge improvement to be able to just pass a map or two instead.

@barbarello

This comment has been minimized.

Copy link

barbarello commented Apr 8, 2016

+1

@kzap

This comment has been minimized.

Copy link

kzap commented Apr 21, 2016

Turns out im not alone in this, made Gist demonstrating this:
https://gist.github.com/kzap/14fc4c9428564dbcff16034219d9fae1

For now i think instead of the complex list, a symlink would work for now

@zzzuzik

This comment has been minimized.

Copy link

zzzuzik commented May 10, 2016

+1

@apparentlymart

This comment has been minimized.

Copy link
Contributor

apparentlymart commented May 10, 2016

Variables being maps and lists is coming in version 0.7, coming soon!

@themalkolm

This comment has been minimized.

Copy link

themalkolm commented May 25, 2016

Is there any workaround?

@marceldegraaf

This comment has been minimized.

Copy link

marceldegraaf commented May 27, 2016

@themalkolm the workaround seems to be to pass two comma-delimited strings (one with keys, one with values) to your module, and then split and group that back together inside the module. See this comment and the one below, and this PR that it links to.

@dbcoliveira

This comment has been minimized.

Copy link

dbcoliveira commented May 31, 2016

Same issue here. its a bit frustrating when you use maps around a generic terraform configuration and suddenly when using module the same approach does work.

@RevCBH

This comment has been minimized.

Copy link
Contributor

RevCBH commented Jul 13, 2016

@apparentlymart - Is this still slated for 0.7 and, If so, is it in the RCs?

@robertwe

This comment has been minimized.

Copy link

robertwe commented Jul 14, 2016

from what I see it works in version: 0.7.0 rc2 46a0709

@kesor

This comment has been minimized.

Copy link

kesor commented Aug 3, 2016

#7493 allows to pass literal maps to modules, not sure about variables though.

@greg-jaunt

This comment has been minimized.

Copy link

greg-jaunt commented Oct 27, 2016

This works for me in 0.7.7, but I had to dig to find the syntax to just pass a map through:

# site.tf
module "modname" {
  source   = "modname"
  mymap = "${var.mymap}"
}
# modname/main.tf
variable "mymap" { type = "map" }
@mitchellh

This comment has been minimized.

Copy link
Member

mitchellh commented Nov 10, 2016

Thanks @greg-jaunt for helping us out.

This indeed does work now!

@mitchellh mitchellh closed this Nov 10, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment