Terraform v0.10.8
...
resource "aws_iam_instance_profile" "master_instance_profile" {
count = "${var.enable_sc == "yes" ? 1 : 0}"
name = "master_instance_profile"
role = "k8sMaster"
}
resource "aws_instance" "dumb-master" {
connection {
timeout = "${var.connection_timeout}"
user = "${var.ansible_user}"
private_key = "${file(var.private_key)}"
}
count = "${var.num_masters}"
ami = "${var.aws_ami}"
instance_type = "${var.aws_instance_type}"
key_name = "${aws_key_pair.keypair.key_name}"
vpc_security_group_ids = ["${var.aws_security_group_id}"]
subnet_id = "${var.aws_subnet_id}"
iam_instance_profile = "${var.enable_sc == "yes" ? "${aws_iam_instance_profile.master_instance_profile.id}" : ""}"
……………………….
}
it should have run without validating the skipped resource.
If the policy and role is all set then I will enable by setting enable_sc to yes otherwise I will set it to no. For the case of enable_sc=yes this works fine.
For the case enable_sc is no terraform fails with below error.
[root@sdl04422 aws]# terraform apply -var-file=aws.local.tfvars.sep30
data.template_file.ansible_config: Refreshing state...
Error: Error running plan: 1 error(s) occurred:
aws_instance.dumb-master: 1 error(s) occurred:
aws_instance.dumb-master: Resource 'aws_iam_instance_profile.master_instance_profile' not found for variable 'aws_iam_instance_profile.master_instance_profile.id'
The reason is quite obvious but seems not logical. Terraform is verifying master_instance_profile resource exists even in case of enable_sc is no i.e iam not at all using this resource. This behavior seems incorrect to me.
I don't believe this is a problem at all since you are essentially attempting to access an attribute of a resource that cannot exist. When you create a resource conditionally, you either need to make sure that any dependent resources are also created conditionally, or ensure that dependent resources have a conditional dependency on the resource. One way of solving this problem is to use the splat syntax:
iam_instance_profile = "${join("", aws_iam_instance_profile.master_instance_profile.*.id)}"
This simply creates a list of all the possible resource ids which you can then join into a string.
In the above Iam accessing resource master_instance_profile if var.enable_sc is yes. However in case of var.enable_sc is no it should go to the else part which is null. however in this scenario it is validating master_instance_profile.
The above alternative will not work for me. My requirement is if the var.enable_sc is no then no roles will be present and master_instance_profile will return error as there is no role. So Iam conditionally skipping the resource. But iam unable to conditionally eliminate the resource key iam_instance_profile in aws_instance resource. Could you please suggest an alternative for my scenario.
Please let me know if you need more information.
That's precisely what the above does, albeit in a roundabout way. If look closely at what is actually happening you'll see that if no resource ids exist, an empty list will be created. Joining an empty list using an empty string produces an empty string which is the output you are expecting.
This
"${var.enable_sc == "yes" ? "${aws_iam_instance_profile.master_instance_profile.id}" : ""}"
produces the same value as
"${join("", aws_iam_instance_profile.master_instance_profile.*.id)}"
however the later will not generate an error if the master_instance_profile resource does not exist.
Thanks for your help. It worked
However just my curiosity...
I still feel in both statements should result in error when condition skipped master_instance_profile resource creation
"${join("", aws_iam_instance_profile.master_instance_profile.*.id)}"
"${var.enable_sc == "yes" ? "${aws_iam_instance_profile.master_instance_profile.id}" : ""}"
it would be great if you could clarify me on why the first statement is not resulting in error though master_instance_profile is referenced (enabled_sc = no).
I'm afraid the specifics as to why "splatting" works when direct references don't are nestled in code that I haven't read, and little documentation on the subject exists, but If I had to take a guess, I'd _assume_ that splats cause attributes to be accessed lazily.
resources = []
for resource in resources:
resource['id']
Basically, in order to access the id attribute for a list of resources, you would need to iterate over the list of resources first. When the number of items in that list is zero, the loop cannot execute, therefore the attribute can't be accessed. On the other hand, when you attempt to access the attribute for a resource that can never exist:
if False:
resource = { 'id' : None }
resource.id
things blow up and rightly so.
Hi,
Thanks for filing the issue. The Interpolation feature you want is being tracked here https://github.com/hashicorp/hil/issues/50,
And we also tracking this in terraform via #11566 and #15605,
Thanks!
@CrankyDragon you want Python not Terraform :)
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
That's precisely what the above does, albeit in a roundabout way. If look closely at what is actually happening you'll see that if no resource ids exist, an empty list will be created. Joining an empty list using an empty string produces an empty string which is the output you are expecting.
This
produces the same value as
however the later will not generate an error if the master_instance_profile resource does not exist.