Skip to content
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

Allow replace_triggered_by to refer to module or module resource #31713

Closed
FWest98 opened this issue Aug 30, 2022 · 9 comments
Closed

Allow replace_triggered_by to refer to module or module resource #31713

FWest98 opened this issue Aug 30, 2022 · 9 comments
Labels
enhancement new new issue not yet triaged

Comments

@FWest98
Copy link

FWest98 commented Aug 30, 2022

Terraform Version

Terraform v1.2.7
on linux_amd64

Use Cases

I would like to have a resource be automatically recreated when one of the subresources of a module is recreated. An example use case would be: a module to deploy and provision a VM; then outside of the module we would add a time_sleep resource that will wait for the provisioning to be done, after which further resources are created. When the VM has to be recreated, I would like to be able to also automatically recreate the timeout.

Attempted Solutions

Currently, attempting to refer a module (or subresource) in the replace_triggered_by field gives an error saying Missing resource reference in replace_triggered_by expression. The best I can do is have a trigger on some output variable of the module.

Proposal

I think it might be tricky to get this right, as I can see the argument of having the module function as a "black box" and that the consuming code shouldn't have to bother with implementation details; allowing a lifecycle dependency on a subresource would break this abstraction and might cause maintenance issues where modules are no longer easily replaceable.

So maybe something is possible on the module level? For example, allowing to depend on the module as a whole and making any change inside the module trigger the recreation of the dependent resource.

References

No response

@FWest98 FWest98 added enhancement new new issue not yet triaged labels Aug 30, 2022
@crw
Copy link
Collaborator

crw commented Aug 31, 2022

Thanks for filing this request!

@apparentlymart
Copy link
Contributor

Hi @FWest98! Thanks for sharing this idea.

I think one crucial part of designing this will be to try to define exactly what a "change inside a module" means.

I say this because we already have one existing behavior where we use a module as a whole as a dependency node: if a module block includes a depends_on for the whole module and Terraform detects a pending change for the dependency then any data resources inside the module must be deferred until the apply step, because the declared dependency isn't specific enough for Terraform to know whether the data source read itself depends on the side-effect.

And we've seen from questions elsewhere that authors find this behavior surprising: their intent was often to single out just a few managed resources inside the module but they used whole-module depends_on for its convenience over wiring the individual dependencies, and so ended up declaring something far more broad than they intended.

I would therefore worry about a similar problem if replace_triggered_by accepted whole modules: an author would probably use it with the intent of it only being affected by a subset of the resources in the module and then be surprised later if e.g. a later version of the module introduces a new resource alongside the ones previously declared and Terraform considered that as sufficient to trigger the replacement. (That's just one example; I'm worried about the whole genre of "more broad than I wanted" situations.)

The comparison to dependencies might also help inform an answer, though: the usual answer to making finer-grain dependencies across a module boundary is to use dependencies on individual input variables and individual output values rather than the module as a whole, and let the dependencies "flow through" those external integration points.

That isn't currently possible for "replace triggering" because Terraform only knows how to walk one hop and check whether the directly-mentioned object has changed. For example, we could investigate the possibility of allowing output values themselves having replace_triggered_by arguments, similar to how output values have depends_on today, and then allow using a specific module output value to trigger replacement of a resource in the parent module.

I think an initial challenge to overcome with that is how it would work with modules that have either count or for_each, since replace triggering is (like dependencies) currently a static thing which can't rely on arbitrary expression evaluation, and so without some redesign it wouldn't be possible to specify which instance key of the module to use. 🤔

@jbardin
Copy link
Member

jbardin commented Aug 31, 2022

Hi @FWest98, this use case was definitely discussed during the initial investigation into this feature. There were many reasons that the triggering events are limited to changes in managed resources, but the reason for the scope being limited to the containing module is more about the fact that the designed scope for all references is limited to the current module. The ability to reference something in an expression outside of one's scope would be quite a major change.

The recommended way to trigger something based on a change in a separate module is to route the desired outputs into a managed resource which can be monitored for changes. Currently the most convent resource for this is a null_resource, but other ideas are being investigated as well. This is also the same pattern used to trigger a change from a temporary value like a local or variable, since that value would need to be stored somewhere in order to detect a change. Having fewer, more flexible patterns like this also tends to simplify the overhead of long-term maintenance (of both Terraform itself, and Terraform configurations), as there are fewer permutations of features to take into account.

@FWest98
Copy link
Author

FWest98 commented Aug 31, 2022

Thanks for both of your replies! I see the issues in both linking to a resource inside a module, and with a resource as a whole, like you describe. Indeed then, I think linking to an output value of a module is the most robust option for nwo, and indeed the pattern with the null_resource "shim" seems like a good temporary workaround! Thanks for that.

I do still think some better overarching vision on replacement-dependencies, cycles and ephemeral resources (as in my other issue) would be good to have in the long term, as currently "plumbing" everything with null_resources feels like a bit of a hack and negatively influences the expressiveness and comprehensibility of TF code.

@jbardin
Copy link
Member

jbardin commented Jan 9, 2023

Given that replace_triggered_by requires a managed resource lifecycle to handle a change, I think we can close this with the adoption of terraform_data (#31757) as the recommended solution supporting all value types.

@jbardin jbardin closed this as completed Jan 9, 2023
@MLNW
Copy link

MLNW commented Jan 19, 2023

@jbardin I'm currently facing this exact problem. When I found this issue I was happy to hear there is a solution. But as far as I can see the referenced merge request has not been part of a release yet. Is that the case? If so, would you know when it might be released?

@jbardin
Copy link
Member

jbardin commented Jan 19, 2023

@MLNW there is no set date for the v1.4 release yet. Note that the intended solution for v1.3 and earlier is to use null_resource. Is is limited to string values, but since you are only concerned with detecting a change, serializing most non-string values to a string should pose no problem.

@MLNW
Copy link

MLNW commented Jan 19, 2023

@jbardin we were able to get a workaround going via an output from our module and using it as a trigger in a null_resource. Still we are looking forward to this new terrform_data resource. Thanks for the quick help :)

@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement new new issue not yet triaged
Projects
None yet
Development

No branches or pull requests

5 participants