-
Notifications
You must be signed in to change notification settings - Fork 9.7k
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
try() function errors on nonexistent resource #24402
Comments
It would be great if you could extend the data resources to have a flag for when they fail but without failing the entire plan so you could handle that as a conditional. |
any news on this? |
any update on this requirement ? |
Another perfect example for this is the chicken/egg issue with Route53 private zones and associations to VPCs, where you have different states (say at VPC level and a global level like Route53). |
My god I can't believe it took me so long googling to find this. What is try() for except conditionally catching and handling errors!? Use case is conditionally adding a workspace identifier tag for resources provisioned from a TFC workspace, typically added to AWS provider default_tags {}. Feels like a pretty obvious requirement:
locals {
tfe_workspace_html_uri = try(
data.tfe_workspace.current.html_url, null)
tf_context_tags = {
"technical:terraform:workspace_url": local.tfe_workspace_html_uri
}
}
provider "aws" {
region = var.region
default_tags {
tags = merge(var.resourcetags, local.tf_context_tags)
}
} |
I am currently facing exactly the same condition as you mentioned |
Has anybody found a workaround for this issue? |
Like others, I need it for data_sources - fail graciously if the underlying query returns no values. |
Same issue on Azure. How do you handle a case where an Azure resource is deleted and Terraform doesn't "see" it during the Terraform Plan ? The Plan generated seems good, Terraform will deploy a child resource... but there's no validation to check whether the parent ressource really exists or not. The Plan looks good, but Apply fails because the parent resource has been deleted outside of Terraform. I'd love to use a data source query to explicitly check if the parent resource exists, since Terraform can't handle it, but then an error is generated and the whole deployment stops :-/ |
The workaround so far (not a very good one though) is to use AWS CLI to get the necessary info.
|
Adding my support for looking into this issue - try() should be able to handle "Error: Reference to undeclared resource" errors: it's one of its major use cases. The fact that the documentation provides examples that just happens to involve accessing potentially missing parts of an existing structure (e.g., array member) just increases the confusion, and never highlights that limitation (=bug). |
➕ 1 on this feature request Not sure if this would work for all of the use cases mentioned above, but there's a proposal for a (hopefully) simple and backwards compatible approach that might work for all(?) use cases:
It's similar to how It also doesn't rely on |
Hi all, The While I can see that code generation does blur the line between "static" and "dynamic", in most cases there's no reason to dynamically check whether a resource is declared because that decision cannot be made dynamically based on runtime data. The It's also not really feasible to catch static errors with a function, because a function call is itself a dynamic operation. A statically invalid expression causes a validation error long before Terraform even begins expression evaluation. If there is something to be solved here then we'll need to solve it in a different way. If you are using code generation to decide whether or not a particular For example, if the code generator decides to generate the resource then it could also generate a local value that refers to it: resource "aws_iam_role" "example" {
# ...
}
locals {
example_iam_role_arn = aws_iam_role.example.arn
} ...but if the code generator decides not to generate the resource then it would still generate a declaration for the same local value name but set it to locals {
example_iam_role_arn = null
} Then other code in the module can refer to output "example_role_arn" {
value = local.example_iam_role_arn
} If you're already doing code generation anyway then I would expect the code generator to use techniques like this to deal with its differences as a code generation concern, rather than using a weird mix of code generation and dynamic decision making together. The other examples given in subsequent comments don't seem to be about code-generation, but I don't really understand what they are about. If you shared a non-code-generation-related use-case in the comments above I'd appreciate if you could share a fuller example of what you are doing so that I can understand more. I suspect that this issue has come to conflate multiple different use-cases just because they led you all to the same error message, and so I'd like to understand those use-cases so that the team can think about potential solutions. |
I can give one example:
That example is simplified, but I hope it gives you a situation that's not code-generation related. Ultimately, it's about being able to use a Again, the issue here is not that the entire "block of text" like |
@apparentlymart my situation is pretty similar to what @MrTrustworthy described, especially with respect to combining the To add to that, there are other situations where the tech you're interfacing with has "virtual" resources. For example, in AWS LakeFormation you can assign permissions to various principals such as IAM roles, IAM users, etc, but also there's this magic principal called There are other cases where third-party tech insists on managing some of the resource lifecycle on its own, meaning there will be inevitable conflicts if you try to import the resources into terraform. You might need to still manage other aspects of it though, so you might do something like: resource "myresource" "foo" {
# ...
}
data "myresource" "bar" {
for_each = # ...
must_exist = false # or nullable = true
}
resource "myresource" "foo_bar_association" {
for_each = data.myresource.bar
foo_id = myresource.foo.id
bar_id = each.value.id
} I think having a |
Hi @MrTrustworthy and @sworisbreathing, I appreciate you taking the time to answer my question. Unfortunately, I don't work on the Terraform team at HashiCorp anymore, so I can't personally do anything to act on your responses, but I did want to note that both of you seem to be discussing the use-case of #16380 rather than the use-case that this issue was about, and so maybe the discussion over there will give you some ideas about different ways to solve your problems. The following is just a personal response and not a statement on behalf of the Terraform team, but for what it's worth... The main challenge with using the existence of something to decide whether to declare something else is that it's an inherent contradiction. You can see this for yourself using the following configuration that uses an existing data source that is already capable of returning an empty result: data "aws_vpcs" "maybe" {
tags = {
Name = "exists"
}
}
resource "aws_vpc" "exists" {
count = length(data.aws_vpcs.maybe.ids) == 0 ? 1 : 0
cidr_block = "10.111.0.0/16"
tags = {
Name = "exists"
}
} If you plan and apply this when no VPC exists, the first plan/apply round will indeed detect that But then if you run another plan/apply round it will then find out that the VPC exists, and so And then if you run again, it'll propose to create again, and so on. This configuration can never converge because it contradicts itself... it says "this Therefore if there is to be a solution for your use-cases, it's gotta be something other than a data source that returns an empty result, or a decision made based on the failure of a data source. However, I can't say if the Terraform team is open to discussing anything like that since the existing issue for this suggestion was already closed. 🤷♂️ |
IMHO if I introduce a nullable data block into my codebase and the result never converges it is a me problem, not a Terraform problem. Every language allows to shot oneself in the foot. There are many existing ways to do it in Terraform. All the mitigations exist already to prevent you to delete the resource by mistake if your configuration is not converging because of a mistake you made, starting with just don't apply that change 😉 As for the data block, I feel like introducing another keyword would be unnecessary, all providers already support the data blocks and allowing me to decide what to do when there are 0 results seems fairly simple to implement. |
Hi, I am facing similar issue while checking if access_entry exist in EKS and if not, I want to create it. The problem for me is if the entry doesn't exist, I get the error.
The error I am getting is:
|
Terraform Version
Terraform Configuration Files
Debug Output
https://gist.github.com/danieladams456/3037dd17100be21f816806450aba6ef8
Expected Behavior
The
try
function should catch the error and returnno role
to the output.Actual Behavior
Steps to Reproduce
terraform init
terraform apply
Additional Context
My use case is for a multi-module terraform project that is generated off a standard template. One resource in one of the modules is sometimes not needed. I would like to be able to gracefully detect if that resource is not present and return
null
in the output. Other modules that consume that output would implement null handling, but I don't want to have to edit mymain.tf
to stop passing around that variable if the resource isn't there. This also lets me just delete the hcl file with that single resource in it vs having to set a flag variable and have both the resource and output be conditional on that.References
none I could find
The text was updated successfully, but these errors were encountered: