Terraform v0.12.0-beta1
assume_role_account_ids = [
"1234567890",
]
locals {
account_role_arns = "${formatlist("arn:aws:iam::%s:role/*", var.assume_role_account_ids)}"
}
data "aws_iam_policy_document" "kube2iam" {
statement {
sid = "AllowToAssumeRoleInAWSAccounts"
actions = [
"sts:AssumeRole",
]
effect = "Allow"
resources = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/*", local.account_role_arns]
}
}
Combining the output of formatlist (a list of strings) and a string inside square brackets should produce one list.
For example:
[["a", "b"], "c"] should equal ["a", "b", "c"]
I get an error telling me that element 1 of the list must be a string, not a list, like so:
Error: Incorrect attribute value type
on roles-policies.tf line 29, in data "aws_iam_policy_document" "kube2iam":
29: resources = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/*", local.account_role_arns]
Inappropriate value for attribute "resources": element 1: string required.
I was able to use these templates in 0.11, but since running the upgrade tool and fixing a couple of errors, this is the only outstanding bit. It's quite possible that my syntax is just wrong, but I can't find anything in the new docs that indicates which bit.
I tried updating it to remove some of the old ${} interpolation syntax as such:
locals {
account_role_arns = formatlist("arn:aws:iam::%s:role/*", var.assume_role_account_ids)
}
data "aws_iam_policy_document" "kube2iam" {
statement {
sid = "AllowToAssumeRoleInAWSAccounts"
actions = [
"sts:AssumeRole",
]
effect = "Allow"
resources = [format("arn:aws:iam::%s:role/*", data.aws_caller_identity.current.account_id), local.account_role_arns]
}
}
but I still get the same error. Is there something I missed in the docs? A fun new append() function? 😉
hi @gilmoregrills! I'm sorry about the confusion here.
There are probably other ways to achieve the same thing, but I believe you can wrap local.account_role_arns in brackets and use concat to join the two lists:
$ terraform console
> concat(["a", "b"], ["c"])
[
"a",
"b",
"c",
]
If you aren't familiar with it, you can use the terraform console command to play around with functions.
In terms of the behavior change from v0.11: It looks like this working was an unintentended consequence of the logic in v0.11 to continue to support redundantly-quoted list expressions for backward compatibility:
foo = ["${aws_instance.foo.*.id}"]
In early versions of Terraform the surrounding brackets were required even though the expression inside returns a list, because early versions of Terraform didn't have lists as a first-class concept, and so the language engine needed those brackets as a hint to interpret the result as a list. After we fixed that issue, we left in an exception that a list-of-lists-of-strings could stand in for a list-of-strings during the transitional period to switch to the (hopefully more intuitive) approach of just using the list result directly.
The implementation of that compatibility behavior was to scan over a list of strings looking for another nested list inside and unwrap it. We didn't intend for that to work as a general mechanism as you were relying on here, but in retrospect it makes sense that it worked that way.
The configuration language changes in v0.12 required that we finally remove that old fallback behavior in order to remove the ambiguity it can cause elsewhere in the language, so we now require that a list of strings really be a list of strings. The upgrade tool does have _some_ logic for fixing this up, but it's focused on single-item situations like the expression above; fixing this fully generally in the upgrade tool would be challenging because we only have certain static information available at upgrade time, so unfortunately I think this is something we'll need to just cover in the upgrade guide as an exceptional case requiring a manual fix.
As @mildwonkey mentioned, concat would be a good way to get this done in v0.12, ensuring that the result is a flat list. Another way would be to use flatten, which is an explicit way to do a similar sort of list-flattening behavior as v0.11 was inadvertently doing implicitly:
resources = flatten([format("arn:aws:iam::%s:role/*", data.aws_caller_identity.current.account_id), local.account_role_arns])
I expect flatten is the method we'll document for migration purposes here since it's the most straightforward way to adapt any existing expression without modifying it too much, but concat is how I would probably write this in new code since I think it makes the intent a little clearer that we're concatenating multiple lists together to produce a single flat list.
Thanks so much for the explanations! I had no idea that using lists/lists-of-lists like that wasn't the intended user behaviour >_< that's interesting to know
I've gone with the concat() in our solution for the purposes of this migration, all works great 👍
Have good weekends!!! 🍹
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.
Most helpful comment
In terms of the behavior change from v0.11: It looks like this working was an unintentended consequence of the logic in v0.11 to continue to support redundantly-quoted list expressions for backward compatibility:
In early versions of Terraform the surrounding brackets were required even though the expression inside returns a list, because early versions of Terraform didn't have lists as a first-class concept, and so the language engine needed those brackets as a hint to interpret the result as a list. After we fixed that issue, we left in an exception that a list-of-lists-of-strings could stand in for a list-of-strings during the transitional period to switch to the (hopefully more intuitive) approach of just using the list result directly.
The implementation of that compatibility behavior was to scan over a list of strings looking for another nested list inside and unwrap it. We didn't intend for that to work as a general mechanism as you were relying on here, but in retrospect it makes sense that it worked that way.
The configuration language changes in v0.12 required that we finally remove that old fallback behavior in order to remove the ambiguity it can cause elsewhere in the language, so we now require that a list of strings really be a list of strings. The upgrade tool does have _some_ logic for fixing this up, but it's focused on single-item situations like the expression above; fixing this fully generally in the upgrade tool would be challenging because we only have certain static information available at upgrade time, so unfortunately I think this is something we'll need to just cover in the upgrade guide as an exceptional case requiring a manual fix.
As @mildwonkey mentioned,
concatwould be a good way to get this done in v0.12, ensuring that the result is a flat list. Another way would be to useflatten, which is an explicit way to do a similar sort of list-flattening behavior as v0.11 was inadvertently doing implicitly:I expect
flattenis the method we'll document for migration purposes here since it's the most straightforward way to adapt any existing expression without modifying it too much, butconcatis how I would probably write this in new code since I think it makes the intent a little clearer that we're concatenating multiple lists together to produce a single flat list.