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

core: Support native lists in Terraform configuration #6322

Merged
merged 3 commits into from
May 4, 2016
Merged

Conversation

jen20
Copy link
Contributor

@jen20 jen20 commented Apr 25, 2016

This pull request adds support for native list variables and outputs, building up on the previous change to state. Interpolation functions now return native lists in preference to StringList.

List variables are defined like this:

variable "test" {
    # This can also be inferred
    type = "list"
    default = ["Hello", "World"]
}

And outputs ca then be defined in terms of the lists:

output "test_out" {
    value = "${var.a_list}"
}

This results in the following state:

...
            "outputs": {
                "test_out": [
                    "hello",
                    "world"
                ]
            },
...

The result of terraform output is as follows:

$ terraform output
test_out = [
  hello
  world
]

Using the output name, an xargs-friendly representation is printed:

$ terraform output test_out
hello
world

The output command also supports indexing into the list (with appropriate range checking and no wrapping):

$ terraform output test_out 1
world

Along with maps, list outputs from one module may be passed as variables into another, removing the need for the join(",", var.list_as_string) and split(",", var.list_as_string) which was previously necessary in Terraform configuration.

This commit also updates the tests and implementations of built-in interpolation functions to take and return native lists where appropriate.

A backwards compatibility note: previously the concat interpolation function was capable of concatenating either strings or lists. The strings use case was deprectated a long time ago but still remained. Because we cannot return ast.TypeAny from an interpolation function, this use case is no longer supported for strings - concat is only
capable of concatenating lists. This should not be a huge issue - the type checker picks up incorrect parameters, and the native HIL string concatenation - or the join function - can be used to replicate the old behaviour.

Finally - StringList is removed, along with all usages of it.

Test coverage can still be improved. All existing tests pass, with the exception of some which were testing for configuration which previously was not valid (e.g. lists in variables...). Several out-of-repo test cases used during development can now be converted to context tests and some additional command tests should be written for the terraform output command.

@jen20
Copy link
Contributor Author

jen20 commented Apr 25, 2016

As an aside - some of this was previously merged prior to the work done to remove flat-maps for map variables and get them to use native lists. Those commits were backed out during rebase of the dev-0.7 branch, so this is for all intents and purposes the "first pass" at lists in light of the maps work.

cc @phinze, @mitchellh.

@phinze
Copy link
Contributor

phinze commented Apr 25, 2016

Starting to dig into this - looking good so far!

Noting that terraform output -help and the docs need updating to document the additional index argument that's supported now.

@phinze
Copy link
Contributor

phinze commented Apr 25, 2016

Found a crasher:

variable "tagsmap" {
  default = {
    some = "tags"
    cool = "beans"
  }
}

resource "aws_vpc" "foo" {
  cidr_block = "10.0.1.0/24"
  tags       = "${var.tagsmap}"
}
❯ tf plan
Refreshing Terraform state prior to plan...


Error running plan: 1 error(s) occurred:

* unexpected EOF
panic: unknown type: "${var.imalist}"
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: goroutine 82 [running]:
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: panic(0x21fdfc0, 0xc820613160)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/.gimme/versions/go1.6.darwin.amd64/src/runtime/panic.go:464 +0x3e6
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ConfigFieldReader).readMap(0xc8205f2f60, 0x3226588, 0x4, 0x0, 0x0, 0x0, 0x0, 0xc81ffd0000, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/field_reader_config.go:150 +0x103b
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ConfigFieldReader).readField(0xc8205f2f60, 0xc820613110, 0x1, 0x1, 0x59be000, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/field_reader_config.go:88 +0x625
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ConfigFieldReader).ReadField(0xc8205f2f60, 0xc820613110, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0xb10000, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/field_reader_config.go:27 +0xc9
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*MultiLevelFieldReader).ReadFieldExact(0xc820625880, 0xc820613110, 0x1, 0x1, 0x3220850, 0x6, 0x0, 0x0, 0x0, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/field_reader_multi.go:31 +0x27c
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ResourceData).get(0xc820341020, 0xc820613110, 0x1, 0x1, 0xc820613102, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/resource_data.go:389 +0x176
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ResourceData).getChange(0xc820341020, 0x3226588, 0x4, 0xc820431201, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/resource_data.go:365 +0x235
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*ResourceData).diffChange(0xc820341020, 0x3226588, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/resource_data.go:342 +0x78
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.schemaMap.diffMap(0xc820429ad0, 0x3226588, 0x4, 0xc82072e5b0, 0xc820612d80, 0xc820341020, 0x0, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/schema.go:718 +0x100
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.schemaMap.diff(0xc820429ad0, 0x3226588, 0x4, 0xc82072e5b0, 0xc820612d80, 0xc820341020, 0x0, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/schema.go:580 +0x2ee
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.schemaMap.Diff(0xc820429ad0, 0xc8205f2bd0, 0xc8205f2c90, 0xc82031f950, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/schema.go:302 +0x1ff
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*Resource).Diff(0xc820324a80, 0xc8205f2bd0, 0xc8205f2c90, 0x7, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/resource.go:163 +0x44
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/helper/schema.(*Provider).Diff(0xc820429c20, 0xc8206c0180, 0xc8205f2bd0, 0xc8205f2c90, 0x1, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/helper/schema/provider.go:175 +0x1c5
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: github.com/hashicorp/terraform/plugin.(*ResourceProviderServer).Diff(0xc82061bc00, 0xc820625000, 0xc820612d30, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/go/src/github.com/hashicorp/terraform/plugin/resource_provider.go:345 +0x76
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: reflect.Value.call(0x2779de0, 0x2fd39b8, 0x13, 0x32197a8, 0x4, 0xc820147ed8, 0x3, 0x3, 0x0, 0x0, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/.gimme/versions/go1.6.darwin.amd64/src/reflect/value.go:435 +0x120d
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: reflect.Value.Call(0x2779de0, 0x2fd39b8, 0x13, 0xc820147ed8, 0x3, 0x3, 0x0, 0x0, 0x0)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/.gimme/versions/go1.6.darwin.amd64/src/reflect/value.go:303 +0xb1
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: net/rpc.(*service).call(0xc820324e80, 0xc820324e40, 0xc820609de0, 0xc82042c180, 0xc820610600, 0x20e1860, 0xc820625000, 0x16, 0x20e18c0, 0xc820612d30, ...)
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/.gimme/versions/go1.6.darwin.amd64/src/net/rpc/server.go:383 +0x1c2
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform: created by net/rpc.(*Server).ServeCodec
go-dynect 2016/04/25 15:08:03 [DEBUG] plugin: terraform:        /Users/phinze/.gimme/versions/go1.6.darwin.amd64/src/net/rpc/server.go:477 +0x49d

@jen20
Copy link
Contributor Author

jen20 commented Apr 25, 2016

Interesting. We should definitely support this.

@jen20
Copy link
Contributor Author

jen20 commented Apr 28, 2016

@phinze the crasher is fixed in 7196fbd. I think this wants further attention in a future PR to fix up sorting list members, which is probably undesirable but currently behaviour which is embedded in the test cases.

@@ -80,6 +84,14 @@ func (n *EvalTypeCheckVariable) Eval(ctx EvalContext) (interface{}, error) {
return nil, fmt.Errorf("variable %s%s should be type %s, got %T",
name, modulePathDescription, declaredType.Printable(), proposedValue)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just caught this error as a user when I didn't declare a type on a module variable and then passed in a map:

❯ tf plan
Error configuring: 1 error(s) occurred:

* variable tags in module mod should be type string, got map[string]interface {}

If I weren't a Go developer this would probably scare me. 😄

Happy to wait for error message twiddling for a subsequent PR though.

@phinze
Copy link
Contributor

phinze commented May 3, 2016

@jen20 this is looking great! LGTM for merge

There are two things I think we should revisit in follow-on PRs:

  • The user-facing error message I mentioned inline
  • Inputs via tfvars / -var / env vars - we discussed this just now and decided that ideally we'd like these to be HCL-compatible, so -var foo='["one","two"]' and TF_VAR_foo='{one = "hello", two = "world"}' work.

@jen20
Copy link
Contributor Author

jen20 commented May 3, 2016

@phinze Agreed on both counts. I'll address these in follow-up commits. For now I'll rebase this onto dev-0.7 (and update dev-0.7 onto the current master) and get it merged!

jen20 added 3 commits May 3, 2016 17:49
This commit adds support for native list variables and outputs, building
up on the previous change to state. Interpolation functions now return
native lists in preference to StringList.

List variables are defined like this:

variable "test" {
    # This can also be inferred
    type = "list"
    default = ["Hello", "World"]
}

output "test_out" {
    value = "${var.a_list}"
}
This results in the following state:

```
...
            "outputs": {
                "test_out": [
                    "hello",
                    "world"
                ]
            },
...
```

And the result of terraform output is as follows:

```
$ terraform output
test_out = [
  hello
  world
]
```

Using the output name, an xargs-friendly representation is output:

```
$ terraform output test_out
hello
world
```

The output command also supports indexing into the list (with
appropriate range checking and no wrapping):

```
$ terraform output test_out 1
world
```

Along with maps, list outputs from one module may be passed as variables
into another, removing the need for the `join(",", var.list_as_string)`
and `split(",", var.list_as_string)` which was previously necessary in
Terraform configuration.

This commit also updates the tests and implementations of built-in
interpolation functions to take and return native lists where
appropriate.

A backwards compatibility note: previously the concat interpolation
function was capable of concatenating either strings or lists. The
strings use case was deprectated a long time ago but still remained.
Because we cannot return `ast.TypeAny` from an interpolation function,
this use case is no longer supported for strings - `concat` is only
capable of concatenating lists. This should not be a huge issue - the
type checker picks up incorrect parameters, and the native HIL string
concatenation - or the `join` function - can be used to replicate the
missing behaviour.
Much celebration may now ensue! ♪┏(°.°)┛┗(°.°)┓┗(°.°)┛┏(°.°)┓ ♪
This adds a test and the support necessary to read from native maps
passed as variables via interpolation - for example:

```
resource ...... {
     mapValue = "${var.map}"
}
```

We also add support for interpolating maps from the flat-mapped resource
config, which is necessary to support assignment of computed maps, which
is now valid.

Unfortunately there is no good way to distinguish between a list and a
map in the flatmap. In lieu of changing that representation (which is
risky), we assume that if all the keys are numeric, this is intended to
be a list, and if not it is intended to be a map. This does preclude
maps which have purely numeric keys, which should be noted as a
backwards compatibility concern.
@jen20 jen20 merged commit 5f4b3ff into dev-0.7 May 4, 2016
@jen20 jen20 deleted the f-native-lists branch May 4, 2016 14:47
@glasser
Copy link
Contributor

glasser commented May 18, 2016

With this change, is it possible to use a variable of type list for a resource field whose schema is type schema.TypeSet (with Elem schema.TypeString)? eg, aws_autoscaling_group's vpc_zone_identifier.

vpc_zone_identifier = "${var.subnet_ids}" gives me vpc_zone_identifier: should be a list even if subnet_ids is a list variable.

@glasser
Copy link
Contributor

glasser commented May 18, 2016

Ah, it's vpc_zone_identifier = ["${var.subnet_ids}"]

@Djuke
Copy link
Contributor

Djuke commented May 27, 2016

I'm playing around with lists and maps in 0.7.0-dev (3355c15) and this is the result:

main.tf

# list test
variable "test_list" {
    default = ["item1","item2"]
}

output "output_list_1" {
    value = "${var.test_list}"
}

output "output_list_2" {
    value = "${element(var.test_list, 0)}"
}

output "output_list_3" {
    value = "${var.test_list.0}"
}

# map test
variable "test_map" {
    default = {
        key1 = "value1"
        key2 = "value2"
    }
}

output "output_map_1" {
    value = "${var.test_map}"
}

output "output_map_2" {
    value = "${lookup(var.test_map, "key1")}"
}

output "output_map_3" {
    value = "${var.test_map.key1}"
}

Output

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

Outputs:

output_list_1 = [
  item1
  item2
]
output_list_2 = item1
output_map_1 = {
  key1 = value1
  key2 = value2
}
output_map_2 = value1

I expected to see output_list_3 and output_map_3.

Version 0.6.16 shows this as a result when only using maps:

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

Outputs:

  output_map_1 = test_map
  output_map_2 = value1
  output_map_3 = value1

Is the 0.7.0-dev output expected behavior in 0.7.0?

jen20 added a commit that referenced this pull request Jun 11, 2016
The work integrated in #6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in #7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
jen20 added a commit that referenced this pull request Jun 11, 2016
The work integrated in #6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in #7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
jen20 added a commit that referenced this pull request Jun 11, 2016
The work integrated in #6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in #7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
@avdhoot
Copy link

avdhoot commented Jun 11, 2016

can i iterate over list variable like count in tf template

jen20 added a commit that referenced this pull request Jun 11, 2016
The work integrated in #6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in #7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
jen20 added a commit that referenced this pull request Jun 11, 2016
The work integrated in #6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in #7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
@ocsi01
Copy link

ocsi01 commented Jun 27, 2016

I'm currently trying the new map passing feature of the 0.7-RC2 and I love it.
However I can't define a map in tfvars. Is it supported?

.tfvars file:
tag_name = '{ Name = "MyTagName3", CustomTag = "Yeahow3"}'

Error parsing terraform.tfvars: At 32:13: illegal char

@sthulb
Copy link

sthulb commented Jul 1, 2016

@ocsi01 Thanks, I was about to report the same thing. @jen20 any ideas?

@carlpett
Copy link
Contributor

carlpett commented Jul 5, 2016

Also having some issues with this, am I supposed to be able to declare an output map like this, or am I getting it wrong?

output "security_group_ids" {
  value = {
    sg1 = "${openstack_networking_secgroup_v2.sg1.id}"
    sg2 = "${openstack_networking_secgroup_v2.sg2.id}"
  }
}

I get output security_group_ids is not a valid type ([]map[string]interface {}).

Version: Terraform v0.7.0-rc2 (46a0709)

@sthulb
Copy link

sthulb commented Jul 5, 2016

@carlpett I have the same issue actually.

@glasser
Copy link
Contributor

glasser commented Jul 5, 2016

Sounds like it's saying the output is a list of maps instead of just one map.

@RevCBH
Copy link
Contributor

RevCBH commented Jul 12, 2016

@ocsi01 - does this work in .tfvars?
tag_name.Name = "MyTagName3"
tag_name.CustomTag = "Yeahow3"

I'm having a similar issue with assigning to an list type var in .tfvars

@flyinprogrammer
Copy link

flyinprogrammer commented Jul 22, 2016

So I'm probably blind, is there a way to merge maps, or append to a map passed into a module?

This is more or less a use case I'm thinking of:

module "app" {
    source = "../app"
    tags = {
        CostCenter = "12435"
        Owner = "John"
    }
    env = "test"
}

--- module ---

resource "aws_instance" "app_instances" {
    count = 3
    ...
    tags = "${concat(var.tags, {Name="app-${count.index}-${var.env}"})}"
}

@rjinski
Copy link

rjinski commented Aug 11, 2016

With the mentioned changed in the PR should this be possible?

output "elb_" {
    value = {
        id = "${aws_elb.public_elb.id}"
        dns_name = "${aws_elb.public_elb.dns_name}"
    }
}

An alternative, working approach is

output "elb" {
    value = "${map("id", aws_elb.public_elb.id, "dns_name", aws_elb.public_elb.dns_name)}"
}

But the former seemed more logical....?

@evankroske
Copy link

The documentation for split still says that module outputs "currently only support string values". Is this documentation out of date?

@apparentlymart
Copy link
Contributor

@rjinski currently the block syntax doesn't work as expected due to a quirk of how the configuration language is parsed. The map function, as shown in your second example, is the right approach for now.

However I totally agree that the former should work, and it hopefully will work that way in a future Terraform version.

grubernaut pushed a commit to hashicorp/terraform-provider-terraform that referenced this pull request Jun 6, 2017
The work integrated in hashicorp/terraform#6322 silently broke the
ability to use remote state correctly. This commit adds a fix for that,
making use of the work integrated in hashicorp/terraform#7124.

In order to deal with outputs which are complex structures, we use a
forked version of the flatmap package - the difference in the version
this commit vs the github.com/hashicorp/terraform/flatmap package is
that we add in an additional key for map counts which state requires.
Because we bypass the normal helper/schema mechanism, this is not set
for us.

Because of the HIL type checking of maps, values must be of a homogenous
type. This is unfortunate, as it means we can no longer refer to outputs
as:

    ${terraform_remote_state.foo.output.outputname}

Instead we had to bring them to the top level namespace:

    ${terraform_remote_state.foo.outputname}

This actually does lead to better overall usability - and the BC
breakage is made better by the fact that indexing would have broken the
original syntax anyway.

We also add a real-world test and assert against specific values. Tests
which were previously acceptance tests are now run as unit tests, so
regression should be identified at a much earlier stage.
@ghost
Copy link

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

Successfully merging this pull request may close these issues.