🚀 Executive Summary
TL;DR: Modern Terragrunt (v0.55+) enforces stricter dependency resolution, causing prompt cascades when applying individual modules due to unresolved outputs. The primary solution involves using `mock_outputs` within `dependency` blocks to provide temporary data, enabling clean bootstrapping and isolated operations without interactive prompts.
🎯 Key Takeaways
- Terragrunt v0.55+ evaluates the entire `terragrunt.hcl` configuration for modules in the dependency chain, leading to prompt cascades if outputs from unapplied dependencies are unresolved.
- `mock_outputs` within `dependency` blocks is the recommended, idempotent solution for bootstrapping new environments and everyday development, providing fake data until real outputs exist.
- `–terragrunt-non-interactive` offers a quick, but dangerous, escape for `plan` runs, while `–terragrunt-include-dir` provides surgical isolation for dependency-free components but breaks the dependency model.
Struggling with Terragrunt’s dependency resolution in modern versions? Learn three practical methods—from a quick command-line flag to the proper use of mock_outputs—to target and apply individual modules within your stack without triggering a cascade of prompts.
How We’re Targeting Individual Units in Terragrunt Stacks Now (And How to Stop the Prompt Cascade)
I still remember the cold sweat. It was 4:45 PM on a Friday, and all I needed to do was push a small change to a single security group rule. I navigated to the directory, typed terragrunt apply, and expected a simple, one-resource plan. Instead, my screen exploded. Terragrunt started asking for input variables for our production EKS cluster, the primary RDS instance, and the shared VPC. My five-minute task was now threatening a full-stack deployment. We’ve all been there—that heart-stopping moment when a tool designed to make life easier suddenly feels like it’s holding your entire infrastructure hostage. This isn’t a bug; it’s a feature of modern Terragrunt’s stricter dependency resolution, and learning to master it is non-negotiable.
So, What Changed? The “Why” Behind the Pain
In the “good old days,” Terragrunt was a bit more lenient. If you targeted a single module, it would often ignore the unresolved dependencies of other modules in the same stack. But starting around version v0.55, Terragrunt got a lot smarter—and stricter. It now attempts to evaluate the entire terragrunt.hcl configuration for every module in your dependency chain, even if you’re just running a plan on a single one.
The root cause? If your `rds` module’s terragrunt.hcl has a dependency "vpc" block, Terragrunt needs to read the VPC’s outputs to render the RDS configuration. When you’re creating the stack from scratch and try to apply just the VPC, Terragrunt still tries to evaluate the RDS config, sees it can’t get the VPC outputs (because they don’t exist yet), and panics, asking you for interactive input. It’s doing its job, but the result is that infamous cascade of prompts that makes bootstrapping a new environment so frustrating.
So, how do we work with this new paradigm? We have a few tools in our belt, ranging from a quick fix to the architecturally sound solution.
Solution 1: The Quick Fix (The “Get Me Out of Here” Flag)
This is your emergency escape hatch. When you’re stuck in prompt hell and just need Terragrunt to move forward, you can use the --terragrunt-non-interactive flag.
terragrunt apply --terragrunt-non-interactive
This tells Terragrunt to not prompt you for inputs and to use the default values (or fall back to `null`) for anything it can’t resolve. It’s fast and it often works for a simple `plan`, but it’s a blunt instrument.
Warning: Use this with extreme caution on an
apply. By telling Terragrunt to proceed without your input, you might be accidentally applying `null` or default values to critical infrastructure components, which can lead to misconfigurations or even data loss. It’s a band-aid, not a solution.
Solution 2: The “Right Way” (Mock Outputs for Clean Bootstrapping)
This is the method Terragrunt’s creators intended for us to use. It involves defining a `mock_outputs` block inside your `dependency` blocks. This gives Terragrunt a “fake” output to use during planning or for modules that haven’t been deployed yet, satisfying its need for data without forcing a prompt.
Imagine you have an `app-service` module that depends on an `eks` cluster. When you’re bootstrapping the environment, the EKS cluster doesn’t exist yet. Here’s how you’d set up the `terragrunt.hcl` for the `app-service`:
dependency "eks" {
config_path = "../eks"
# This is the magic!
# Provide fake data for Terragrunt to use when the real outputs don't exist yet.
mock_outputs = {
cluster_oidc_provider_arn = "arn:aws:iam::123456789012:oidc-provider/fake-oidc-provider"
cluster_endpoint = "https://fake-cluster-endpoint.local"
cluster_name = "temp-mock-name"
}
# This prevents Terragrunt from trying to run 'init' or 'plan' on the dependency
# if it's not already applied. Highly recommended.
skip_outputs = true
}
inputs = {
eks_cluster_name = dependency.eks.outputs.cluster_name
eks_cluster_oidc = dependency.eks.outputs.cluster_oidc_provider_arn
}
With this in place, when you run terragrunt plan in the `app-service` directory before the EKS cluster is deployed, Terragrunt will happily use the mock values. Once you run terragrunt apply-all or apply the EKS module, Terragrunt will automatically switch to using the real outputs. This is the cleanest, most reliable, and idempotent way to manage dependencies.
Pro Tip: You can use the
mock_outputs_allowed_terraform_commandsattribute inside the dependency block to restrict when mocks are used, for example, only allowing them forplanandvalidatecommands. This adds an extra layer of safety.
Solution 3: The “Nuclear Option” (Targeted Directory Inclusion)
Sometimes, you need to perform a surgical strike. You want to operate on a single module and tell Terragrunt to ignore everything else in the universe. For this, you can use the --terragrunt-include-dir flag.
Let’s say you absolutely must destroy and re-create a specific network ACL module without triggering any other dependency checks:
terragrunt destroy --terragrunt-include-dir ./networking/nacl/
This command forces Terragrunt to only consider the configuration within that specific directory. It won’t walk up the tree to find a root `terragrunt.hcl` and it won’t try to resolve dependencies from other modules like `vpc` or `subnets`. It’s a powerful tool for isolation.
The downside? It completely breaks the dependency model. If the module you’re targeting actually needs an output from another module, this command will fail because Terragrunt has been explicitly told to ignore that other module. This is best used for modules with no dependencies or when you are performing a very specific, isolated task and understand the risks.
Which Method Should You Use? A Quick Comparison
| Method | Best Use Case | Pros | Cons |
|---|---|---|---|
The Quick Fix--terragrunt-non-interactive |
Emergency `plan` runs or when you’re stuck in a CI/CD pipeline. | Extremely fast, requires no code changes. | Dangerous for `apply`, hides underlying configuration issues. |
The “Right Way”mock_outputs |
Bootstrapping new environments, everyday development, and CI/CD. | Idempotent, safe, and the intended pattern. Makes dependencies explicit. | Requires more upfront configuration in your terragrunt.hcl files. |
The “Nuclear Option”--terragrunt-include-dir |
Destroying/re-creating isolated, dependency-free components. | Total isolation, ignores the rest of the stack completely. | Breaks dependency resolution; will fail if the module needs outputs from elsewhere. |
Ultimately, my team and I have made a hard pivot to using mock_outputs for everything. It felt like a bit of extra work at first, but the stability and predictability it brought to our deployments, especially when onboarding a new engineer or building a DR environment from scratch, have been invaluable. Save the other flags for the rare exceptions they were designed for. Your future self (at 5:00 PM on a Friday) will thank you.
🤖 Frequently Asked Questions
âť“ How do I prevent Terragrunt from prompting for inputs when applying a single module in a stack?
To prevent prompt cascades, use `mock_outputs` within your `dependency` blocks to provide temporary, fake data for outputs that don’t yet exist. For emergency `plan` runs, `–terragrunt-non-interactive` can be used with extreme caution, or `–terragrunt-include-dir` for isolated, dependency-free operations.
âť“ How do `mock_outputs` compare to other methods for targeting individual Terragrunt units?
`mock_outputs` is the safest, most idempotent, and architecturally sound method for managing dependencies during bootstrapping and daily operations. `–terragrunt-non-interactive` is a blunt instrument, dangerous for `apply`, and `–terragrunt-include-dir` offers total isolation but breaks dependency resolution, suitable only for very specific, isolated tasks.
âť“ What’s a common implementation pitfall when trying to apply a single Terragrunt module in a new stack?
A common pitfall is Terragrunt’s stricter dependency resolution (v0.55+), which attempts to evaluate the entire configuration and prompts for inputs when dependent module outputs don’t yet exist. The solution is to define `mock_outputs` within `dependency` blocks to satisfy Terragrunt’s need for data during initial deployments.
Leave a Reply