Terraform: Variable cannot contain interpolation

Created on 14 Dec 2016  ยท  16Comments  ยท  Source: hashicorp/terraform

I am trying to create status check cloudwatch alarm that will be applicable to all instances :

In variables file :

variable "hostnames" {
default = {
"0" = "www-l01"
"1" = "www-l02"
"2" = "aps-l01"
"3" = "aps-l02"
}
}

variable "instanceid" {
default = {
"0" = "${aws_instance.www-l01.id}"
"1" = "${aws_instance.www-l02.id}"
"2" = "${aws_instance.aps-l01.id}"
"3" = "${aws_instance.aps-l01.id}"
}
}

In cloudwatch file :-

resource "aws_cloudwatch_metric_alarm" "status_check" {
count = 2
alarm_name = "${lookup(var.hostnames, count.index)}"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "StatusCheckFailed"
namespace = "AWS/EC2"
statistic = "SampleCount"
threshold = "2"
period = "60"
alarm_description = "Status Check of Instance"
insufficient_data_actions = []
dimensions {
InstanceId = "${lookup(var.instanceid, count.index)}"
}
alarm_actions = ["arn:aws:automate:eu-west-1:ec2:recover"]
}

While executing it gave me below error :-

module root: 1 error(s) occurred:

  • Variable 'instanceid': cannot contain interpolations

Any idea about best way to resolve this ?

Most helpful comment

completely agree with @pasali, @sidhurana you should strive to create the instances using count. If for some reason you need two different aws_instance setups then take a look at the previous example with concat. You can try my previous suggestion to see if things are working as expected but switching to a count based creation of aws_instance will provide you a way of changing the number of instances without worrying about managing the list manually.

All 16 comments

@sidhurana as far as I know terraform does not support interpolations in variables see #4397

@pasali : Thanks , Do you know any other way to achieve this ?

@sidhurana, i did not quite understand what you are trying to achieve, but i assume you want to get all instance ids So you can do something like that:

dimensions {
  InstanceId = "${aws_instance.your-resource-name.*.id}"
}

let me know if this works for you.

@sidhurana extending @pasali proposal, you can concatenate two lists into one.

https://www.terraform.io/docs/configuration/interpolation.html#concat_list1_list2_

dimensions {
  InstanceId = "${concat(aws_instance.www.*.id, aws_instance.aps.*.id)}"
}

in order to make this work you must generate your instances using the "count" parameter and not by declaring them separately.

Another alternative would be to create a list element by element using https://www.terraform.io/docs/configuration/interpolation.html#list_items_

dimensions {
  InstanceId = "${list(aws_instance.www-l01.id, aws_instance.www-l02.id, aws_instance.aps-l01.id, aws_instance.aps-l01.id)}"
}

the same way you can create a map like this
https://www.terraform.io/docs/configuration/interpolation.html#map_key_value_

dimensions {
  InstanceId = "${map("0", aws_instance.www-l01.id, "1", aws_instance.www-l02.id, "2", aws_instance.aps-l01.id, "3", aws_instance.aps-l01.id)}"
}

@pasali : Thanks. yes, I am trying to get all instance ID's so i can pass it to cloudwatch resource and that will create cloudwatch alarm for all instances all at once.
@martin-flaregames : Thanks for examples and reference pages.

I am getting below error while trying above map and list examples in InstanceId:

  • dimensions: 1 error(s) decoding:
  • '[InstanceId]' expected type 'string', got unconvertible type 'map[string]interface {}'
  • dimensions: 1 error(s) decoding:

Well the examples just show you how to create a list or a map outside a variable declaration, but the "IsntanceId" entry in "dimensions" expects only a single string. So you still need to iterate over the items using the count property of aws_cloudwatch_metric_alarm.

Btw, you do not need a map for this, you can use element instead of lookup when using lists.
https://www.terraform.io/docs/configuration/interpolation.html#element_list_index_

Possibly the best alternative would be to create a module accepting a list of instance IDs as parameter. I could build such an example for you, but it will take time.

@sidhurana this should do the trick

dimensions {
  InstanceId = "${element(aws_instance.your-resource-name.*.id, count.index)}"
}

@martin-flaregames : Thanks for your input.

@pasali : Thanks.. I have spawned instances by declaring them separately. I think it will work perfectly in case all instances created by count parameter. So, in my case i have different resource names for all instances.

Please correct me if I am wrong.

@sidhurana try combining @pasali solution with the previously proposed list interpolation.

```
dimensions {
InstanceId = "${element(list(aws_instance.www-l01.id, aws_instance.www-l02.id, aws_instance.aps-l01.id, aws_instance.aps-l01.id), count.index)}"
}
````

@sidhurana you can try what @martin-flaregames suggested. But personally i would use count parameter to create instances. If you use count parameter, your resource declarations will be more dynamic.

completely agree with @pasali, @sidhurana you should strive to create the instances using count. If for some reason you need two different aws_instance setups then take a look at the previous example with concat. You can try my previous suggestion to see if things are working as expected but switching to a count based creation of aws_instance will provide you a way of changing the number of instances without worrying about managing the list manually.

@martin-flaregames: It works perfectly.
@pasali : Yeah, I agreed. I will try to change my terraform config.

@sidhurana you may proceed to close the issue if you have no further questions or remarks :)

And please notice that there may be a bug in your original list: aws_instance.aps-l01.id is listed twice. You may have intended to say aws_instance.aps-l02.id. This is another argument for using count ;)

I'm closing it as well since we have issues to cover the feature request and this issue isn't a bug. Thanks everyone for helping!

@martin-flaregames :Yeah , that was typo..I agree that using count will avoid such errors and will shorten code as well... Thanks all for helping.

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