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

Conditional expression does not always work in output variable #15165

Closed
jkehres opened this Issue Jun 7, 2017 · 8 comments

Comments

Projects
None yet
4 participants
@jkehres

jkehres commented Jun 7, 2017

Terraform Version

0.9.7

Affected Resource(s)

Output variables

Terraform Configuration Files

provider "aws" {
	region = "us-east-1"
}

variable "topic_arn" {
	default = ""
}

resource "aws_sns_topic" "my_topic" {
	count = "${var.topic_arn != "" ? 0 : 1}"
	name = "my-topic"
}

output "topic_arn" {
	value = "${var.topic_arn != "" ? var.topic_arn : aws_sns_topic.my_topic.arn}"
}

Expected Behavior

When a non-empty value is given for the topic_arn input variable, the output variable topic_arn should be present.

Actual Behavior

When a non-empty value is given for the topic_arn input variable, the output variable topic_arn is missing:

$ terraform apply -var "topic_arn=arn:aws:sns:us-east-1:000000000000:foobar"

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

However, when an empty (default) value is given for the topic_arn input variable, the output variable topic_arn is present:

$ terraform apply
aws_sns_topic.my_topic: Creating...
  arn:    "" => "<computed>"
  name:   "" => "my-topic"
  policy: "" => "<computed>"
aws_sns_topic.my_topic: Creation complete (ID: arn:aws:sns:us-east-1:358315610143:my-topic)

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path:

Outputs:

topic_arn = arn:aws:sns:us-east-1:358315610143:my-topic

Steps to Reproduce

Run the following command with the HCL file shown above:

$ terraform apply -var "topic_arn=arn:aws:sns:us-east-1:000000000000:foobar"
@apparentlymart

This comment has been minimized.

Contributor

apparentlymart commented Jun 7, 2017

Hi @jkehres! Sorry for the weird behavior here.

I think what you're actually seeing here is the bug discussed in #9080: errors while evaluating outputs are not shown today, because we want to be able to try to evaluate outputs before all of their inputs are complete.

This is also related to hashicorp/hil#50, which means that right now both "sides" of the conditional need to always be valid, even though only one is ever used.

Were you to try the expression you have there in a resource attribute, I think you'd get an error saying that aws_sns_topic.my_topic.arn doesn't exist, because the count is zero.

Here's a different way to write it that should work:

value = "${element(compact(concat(list(var.topic_arn), aws_sns_topic.my_topic.*.arn)), 0)}"

This should work because in both cases all of the variables can be resolved:

  • When var.topic_arn is empty, the initial list is ["", "(the arn of the resource)"]. compact removes the empty element from the front, so element 0 is "(the arn of the resource)".
  • When count = 0, the "splat syntax" expands to an empty list, so the initial list is ["(the value of topic_arn)"], and so element 0 is "(the value of topic_arn)".

I totally understand that this convoluted expression creates maintenance headaches, so we're planning to address the limitations here and make this behave in a more intuitive way in future.

Since we already have issues open covering the different aspects of this, I'm going to close it just to keep any further discussion in one place. Thanks for filing this issue!

@rhibiscusc

This comment has been minimized.

rhibiscusc commented Aug 3, 2017

@apparentlymart I tried to adopt the idea of using "splat syntax" to workaround similar issue. but it does not work:

original:

  • aws instance example2 is created only when var.flag=="true"

output test_list {
value = ["${split(" ", var.flag == "true" ? "${aws_instance.example1.id} ${aws_instance.example2.id}" : "${aws_instance.example1.id}")}"]
}

workaround tried with splat syntax:

value = ["${compact(concat(list(aws_instance.example1.id), aws_instance.example2.*.id))}"]

both result in missing output of test_list.

would you please suggest alternative to workaround this? I am using terraform v0.10.0

Thanks

@jnoxon

This comment has been minimized.

jnoxon commented Aug 24, 2017

@rchenv did you find a workaround for this? I'm stuck here, too.

@rhibiscusc

This comment has been minimized.

rhibiscusc commented Aug 24, 2017

@jnoxon I did find a workaround:

value = ["${compact(concat(aws_instance.example1.*.id, aws_instance.example2.*.id))}"]

does the trick.

@apparentlymart

This comment has been minimized.

Contributor

apparentlymart commented Aug 24, 2017

Sorry I didn't see these responses before... it's hard to keep track of discussions in closed issues. 😞 I'm glad to see you found a workaround in spite of my not seeing your question, @rchenv.

For anyone else who finds this here: to work around the current issue that output errors are hidden, one approach is to evaluate the same expression in terraform console to see what error it produces. The errors today unfortunately aren't always the most helpful -- we're planning to work on this in the near future -- but at least it's a better clue about what Terraform was taking issue with.

Note that terraform console behaves as if what you type is automatically wrapped in ${ ... }, so the thing to type into the console would be compact(concat(aws_instance.example1.*.id, aws_instance.example2.*.id)) rather than the full ${compact(concat(aws_instance.example1.*.id, aws_instance.example2.*.id))}.

@rhibiscusc

This comment has been minimized.

rhibiscusc commented Aug 24, 2017

@apparentlymart Thanks for the info on terraform console. I have not used it before. that is a great time-saving tool!

@jnoxon

This comment has been minimized.

jnoxon commented Aug 24, 2017

I tried to boil down what I am doing to something very simple:

variable "use_random" { default = false }
variable "number" { default = 5 }

resource "random_id" "optional" {
   count = "${var.use_random}"
   byte_length = 1
}

output "result" {
  value = "${element(compact(concat(random_id.optional.*.id, list(var.number))),0)}"
}

This works, but if I deploy it with use_random=true and then deploy again with use_random=false, I get no output from the second deploy. If I make no changes and deploy again, it works!

@apparentlymart

This comment has been minimized.

Contributor

apparentlymart commented Aug 24, 2017

@jnoxon that sounds like you've found a new bug, where perhaps the output isn't getting re-evaluated properly as the number of random id resources goes to zero. Would you mind opening a fresh issue for that?

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