Closed tbugfinder closed 4 years ago
Input to os_config
is
os_config = {
disable_password_authentication = false
}
So there's no map of ssh_keys
set, it should be skipped.
Hi @tbugfinder,
Unfortunately because this sort of dynamic block construction wasn't actually intentionally supported in 0.11 and was only working due to a number of validation bugs and coincidences, the upgrade process for this particular usage is just making a best effort based on common patterns we saw in a review of examples shared on GitHub and via the Terraform Registry. It looks like your 0.11 config here was doing something slightly different that the upgrade tool can't handle.
I'm honestly not sure exactly how Terraform 0.11 was interpreting what you had before, but from looking at your full example it seems like your goal is for os_config
to be optional and to generate the block only if the caller sets it. The more common pattern that the upgrade tool is assuming here is that your optional argument would be a list and thus an empty list would be a suitable fallback if it isn't set.
In your case it seems to be a single nested object, and so we need a slightly different approach. I think the following is the smallest possible 0.12 adaptation of what you had, which I'd recommend while you're completing the upgrade process just to minimize the risk of accidental changes in behavior. (You might want to adjust this to use the 0.12 features in a different way later, but better to get your migration completed first and then iterate on the details.)
dynamic "ssh_keys" {
for_each = contains(keys(os_profile_linux_config.value), "ssh_keys") ? [os_profile_linux_config.value.ssh_keys] : []
content {
key_data = ssh_keys.value.key_data
path = ssh_keys.value.path
}
}
The contains
condition in the above should return true
only if the ssh_key
key is present, in which case the overall result will be a single-element list containing your ssh_keys
object, producing in turn a single ssh_keys
block. Otherwise the overall result will be an empty list and so no ssh_keys
blocks will be produced at all.
That conditional is admittedly quite awkward. There's a new feature in the master
branch planned for inclusion in the forthcoming 0.12.20 release which could make it a little more concise:
for_each = try([os_profile_linux_config.value.ssh_keys], [])
This new try
function will try to evaluate each of its arguments in turn and return the first one that doesn't produce any errors. In this case that means it'll first try to construct a single-element list containing the ssh_keys
value, but if that fails (likely because ssh_keys
doesn't exist) then it'll try to construct an empty list, which always succeeds. This is the sort of feature where it can really hurt understandability if overused, but I expect it'll be handy for situations like this where a module is receiving a data structure whose shape isn't predictable.
Thank You @apparentlymart - that's the solution.
Great, thanks for following up @tbugfinder!
Since terraform 0.12upgrade
is essentially frozen now (to avoid situations where folks who upgraded at different times might see subtly different results), I'm going to close this out.
I think even if we were still improving the upgrade tool, there wouldn't really be a good way to infer this because static analysis here (which is what the upgrade tool is relying on) doesn't have enough information to determine the final type of ssh_keys
. Indeed, this sort of ambiguity is why the tool tends to generate a TF-UPGRADE-TODO
in this situation, so that the person running the upgrade can consider what types they are expecting and adjust as needed. :confounded:
Thanks for reporting this, and for confirming that the proposed solution worked!
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.
Terraform Version
Terraform Configuration Files
Debug Output
Crash Output
Expected Behavior
terraform plan
finishes successfully and applies upgraded code :-)Actual Behavior
After upgrade initial
terraform plan
output is:This code was upgraded from 0.11.14 to HCL2 using terraform 0.12. As added by the tool there is a post upgrade task included. Unfortunately I couldn't figure out how to resolve it yet.
dynamic "ssh_keys"
is a map, so I can convert to it, however it's dynamic and it might exists or might not.I found a post by @apparentlymart and switched that for_each to
for_each = { for v in os_profile_linux_config.value : v => v }
. After that the error message is:Steps to Reproduce
Additional Context
References