Description
The problem I am currently facing with the new Stacks RFC is that it is not possible to pass the output of one unit through to the values of another in the terragrunt.stack.hcl
file.
While it is possible to do this in the unit definition, this is not extensible enough because, with stacks, the units will be reused with different inputs.
Proposal
Expand the terragrunt.values.hcl file to use dependencies:
# terragrunt.stack.hcl
unit "dep" {
source = "modules/imadep"
path = "imadep"
}
unit "test" {
source = "modules/test"
path = "test"
values = {
a = "a"
b = unit.dep.output_b
}
}
# .terragrunt-stack/test/terragrunt.values.hcl (auto-generated)
values {
a = "a"
b = dependency.dep.outputs.output_b
}
dependency "dep" {
config_path = "../imadep"
}
There is a POC of this here: #4056
POC Q&A
Recommendation to use a new terragrunt.dependencies.hcl file
I'd be happy to POC this, but I'm curious how you see the relationship between the dependencies file, values file, and terragrunt file.
My current view is that consolodating all dynamic inputs to units in the terragrunt.values.hcl is optimal:
values {
a = "a"
b = dependency.dep.outputs.output_b
}
dependency "dep" {
config_path = "../imadep"
}
Yes, it is more complex than just putting (static) key-value pairs. However:
- the complexity has to go somewhere
- Putting this inside of the values file may be the least complex
Why is this the least complex?
- I think it can clearly define interfaces and boundaries between components:
terragrunt.values.hcl
can be processed (i.e. dependencies resolved) and only export a singlevalues
interface. Processing would be self-contained to the terragrunt.values.hcl file, and terragrunt.hcl would only ever see thevalues
object from it. - I suspect there may be other constructs that users may want to add in the future. Splitting files by block types may lead to many files with different kinds of relationships between them.
What if two dependencies are named the same thing across these different files? What's the behavior? Can the terragrunt.hcl file make reference to them?
I think the correct choice is to make the terragrunt.values.hcl file hide it's internals and only expose only an interface for retrieving the values. This helps with composability (If there is a dependency in the values file with the same name as a dependency in the terragrunt file, they will not interfere).
Are there any alternative designs that you think would work just as well?
The constraint to keep unit definitions backwards compatible (which I agree with!) reduces the solution space. I haven't been able to come up with another design.
How are mock outputs handled?
I touch on one option for this at the bottom of this comment #3313 (comment), but there are benefits to not implementing this: it trades a simple interface for flexibility. However, with additional changes it may be possible to get the flexibility of mocks with the benefits of a simple interface, and it boils down to where the mocks are defined. Instead of defining them at the "dependency" block, mock outputs could be defined at either or both of (1) the referenced units (the unit would define it's own mock outputs), and (2) in a new mock_inputs
block, which is decoupled from the dependency block. I think it makes sense for a module to define mock_outputs, because the author should know what format the output takes. At the same time, I can see the value of defining mock_inputs for certain use-cases (if the dependency's output is dynamic enough where a static mock_output isn't enough).