-
Notifications
You must be signed in to change notification settings - Fork 1
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
Fix inconsistent plan error #218
Conversation
This is a temprorary(?)/partial(?) fix for the inconsistent plan error. As part of creating the examples for (#203) I was running into this issue and noticed that all of the occurrences were due to the `terraform_data` resources changing from `null` to `""`. Adding this simple `try` function to always fallback to `""` seems to have fixed the issue in a lot of cases. This obviously doesn't fix the inconsistent plan issue in all cases, but it gets us unstuck for creating example tests. re #198
This change is part of the following stack: Change managed by git-spice. |
Can you reference what So in case of an error this will swallow data which is not great. We need some creative thinking here actually, and this got me thinking about other functions we can use: https://developer.hashicorp.com/terraform/language/functions/nonsensitive These look intriguing. What if we abandoned wrapping module outputs in terraform_data but instead directly exported them as we did before the workaround from the top-level module, but this time instead of propagating the module M's output o we would propagate Will this work? ONe interesting case if sensitive bits are not at the top-level of |
This is interesting, let me give it a shot. |
This is great! Can we pin it with a simple test? Also with regard to testing I was curious if Apparently it is not recursive so we have this: Example: module "m" {
source = "./m"
inputvar = sensitive(10)
}
output "exposed" {
value = nonsensitive(module.m.outputvar)
} With this module: inputs.tf: variable "inputvar" {
type = number
default = 16
} infra.tf: resource "random_string" "random" {
length = 16
special = true
override_special = "/@£$"
} outputs.tf: output "outputvar" {
value = {
"X" = var.inputvar,
"A" = "B"
}
} I get the dreaded:
|
I've tried this but similarly issensitive is non-recursive so it does not detect the presence of nested secrets 🤔 module "webservers" {
source = "./webservers"
inputvar = sensitive(10)
}
output "exposed" {
value = module.webservers.outputvar
sensitive = true
}
output "exposed_is_sensitive" {
value = issensitive(module.webservers.outputvar)
}
|
I think this solution doesn't work generally. Because of the non-recursive issue in these functions. I'm sorry. If we want to support full generality we still need to write our own TF provider it seems like, and perhaps the tweaked terraform_data is the lowest lift. If we are looking for workarounds that do not address secret handling in full generality, we can consider not supporting first-class secrets or supporting them in an over-approximating manner.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, seems to work!
One limitation I think we still have is secret floating, if any of the innards of an output are secret, the entire thing is secret. That is acceptable for starters, we can document this.
mOutputs[fmt.Sprintf("%s%s", terraformIsSecretOutputPrefix, output.Name)] = map[string]interface{}{ | ||
"value": fmt.Sprintf("${issensitive(module.%s.%s)}", name, output.Name), | ||
mOutputs[fmt.Sprintf("%s%s", terraformIsSecretOutputPrefix, output.Name)] = map[string]any{ | ||
"value": fmt.Sprintf("${jsondecode(issensitive(jsonencode(module.%s.%s)))}", name, output.Name), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just be :
issensitive(jsonencode(module.%s.%s))
Do we need outer jsondecode? issensitive returns bool right?
This is a fix for the inconsistent plan error.
Background
To expose outputs from a module, we need to account for the secretness of the outputs
If you try and output a secret value without setting
sensitive: true
in the outputThe deployment will fail. We also need to be able to handle this dynamically since we won't know
the secret status until after the operation, and we need to write the output definition when we create the file (before the operation).
Previous Solution
In #132 we added support for module outputs by using a
terraform_data
resource as a proxy for the output. This allowed us to account for the dynamic nature of the secret since we could determine the secret status of the value using the same method that we use for all other resource properties.This ran into an issue #198 where
terraform_data
resources cannot be used if the value may be "inconsistent". A very common case that is used in most modules is to define an output like this:try
is used because most modules will conditionally create resources and need to handle the case where the resource was not created and the value doesn't exist. This is a common case, but there may be other cases of this "inconsistent" data.New Solution
This PR tries a new solution of using output values with a combination of the nonsensitive and issensitive functions. We can use the
issensitive
function to dynamically determine whether the value is sensitive or not. Unfortunately it is not possible to use functions in theoutput.sensitive
field (e.g.sensitive: "${issensitive(module.source_module.output_name1)}"
won't work).To work around this we use two outputs for each output value:
fixes #198