Skip to content

Commit 36409fa

Browse files
authored
feat: remote state reading for GCP and Azure (#6710)
* feat: remote state reading for GCP and Azure * chore: azure depdnency outputs reading * chore: internal output * PR cleanup * chore: PR cleanup * chore: state backend reading * chore: state cleanup * chore: cleanup * chore: cleanup * chore: merge fixes * chore: merge main in * chore: release notes update * chore: remote state cleanup * chore: tests upadte * test: update malformed state assertion for Go 1.27 * chore: lock test fix * chore: azure remote state update * PR comments * chore: depdendencies cleanup * docs: import Before/Since in terminology page * chore: PR comments
1 parent 41d410f commit 36409fa

47 files changed

Lines changed: 4548 additions & 227 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/src/content/docs/01-getting-started/04-terminology.md renamed to docs/src/content/docs/01-getting-started/04-terminology.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ sidebar:
66
order: 4
77
---
88

9+
import Before from '@components/Before.astro';
10+
import Since from '@components/Since.astro';
11+
912
Infrastructure as Code (IaC) tooling necessarily requires a lot of terminology to describe various concepts and features due to the breadth of the domain.
1013

1114
Whenever possible, Terragrunt terminology attempts to align with wider industry standards, but there are always exceptions. There are going to be times when certain terms are used in different tools, but have special meaning in Terragrunt, and there are times when the same term might have different meaning in different contexts.
@@ -223,7 +226,13 @@ By default, Terragrunt will interact with OpenTofu/Terraform in order to retriev
223226

224227
Terragrunt does have the ability to mock outputs, which is useful when dependencies do not yet have outputs to be consumed (e.g. during the run of a unit with a dependency that has not been applied).
225228

229+
<Before version="1.1.4">
226230
Terragrunt also has the ability to fetch outputs without interacting with OpenTofu/Terraform via [--dependency-fetch-output-from-state](/reference/cli/commands/run#dependency-fetch-output-from-state) for dependencies where state is stored in AWS. This is an experimental feature, and more tooling is planned to make this easier to use.
231+
</Before>
232+
233+
<Since version="1.1.4">
234+
Terragrunt also has the ability to fetch outputs without interacting with OpenTofu/Terraform via [--dependency-fetch-output-from-state](/reference/cli/commands/run#dependency-fetch-output-from-state) for dependencies using a supported remote-state backend. This is an experimental feature, and more tooling is planned to make this easier to use.
235+
</Since>
227236

228237
### Feature
229238

docs/src/content/docs/03-features/01-units/03-state-backend.mdx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ remote_state {
341341

342342
- `skip_bucket_versioning` — Skip versioning on the state bucket. Use only if the object store does not support versioning.
343343
- `enable_bucket_policy_only` — Enable uniform bucket-level access. See [uniform bucket-level access](https://cloud.google.com/storage/docs/uniform-bucket-level-access) for details.
344-
- `encryption_key` — A Cloud KMS key name to use for encrypting state objects.
344+
- `encryption_key` — A base64-encoded 32-byte customer-supplied encryption key used to read and write state objects.
345345

346346
If you experience an error for any of these configurations, confirm you are using Terraform v0.12.0 or greater.
347347

@@ -361,8 +361,11 @@ OpenTofu/Terraform's native `azurerm` backend is used as-is.
361361
</Before>
362362
<Since version="1.1.2">
363363
With the experiment enabled, Terragrunt bootstraps, deletes, and migrates Azure Storage state resources.
364-
Otherwise, these operations return an error. Reading and writing the state itself is always handled by
365-
OpenTofu/Terraform's native `azurerm` backend.
364+
Otherwise, these operations return an error. OpenTofu/Terraform's native azurerm backend handles normal state reads and writes.
365+
366+
<Since version="1.1.4">
367+
When both `azure-backend` and [`dependency-fetch-output-from-state`](/reference/experiments/active#dependency-fetch-output-from-state) are enabled, and the Azure backend configuration is supported by the direct reader, Terragrunt reads dependency outputs directly from the Azure state blob. Otherwise it uses the native output path.
368+
</Since>
366369
</Since>
367370
</Aside>
368371

docs/src/content/docs/06-troubleshooting/03-performance.mdx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,13 @@ Under the hood, Terragrunt dependency blocks leverage the OpenTofu/Terraform `ou
124124

125125
The OpenTofu/Terraform `output -json` command does a bit more work than simply fetching output values from state, and a significant portion of that slowdown is loading providers, which it doesn't really need in most cases.
126126

127+
<Before version="1.1.4">
127128
You can significantly improve the performance of dependency blocks by using the [`dependency-fetch-output-from-state`](/reference/experiments/active#dependency-fetch-output-from-state) experiment. When the experiment is active, Terragrunt will resolve outputs by directly fetching the backend state file from S3 and parse it directly, avoiding any overhead incurred by calling the `output -json` command of OpenTofu/Terraform.
129+
</Before>
130+
131+
<Since version="1.1.4">
132+
You can significantly improve the performance of dependency blocks by using the [`dependency-fetch-output-from-state`](/reference/experiments/active#dependency-fetch-output-from-state) experiment. When the experiment is active for a supported backend, Terragrunt resolves outputs by fetching and parsing the backend state object directly, avoiding any overhead incurred by calling the `output -json` command of OpenTofu/Terraform.
133+
</Since>
128134

129135
For example:
130136

@@ -134,9 +140,15 @@ terragrunt run --all plan --experiment=dependency-fetch-output-from-state
134140

135141
#### Fetching Output From State - Gotchas
136142

137-
<Card title="S3 backends only" icon="information">
143+
<Card title="Supported backends" icon="information">
138144

145+
<Before version="1.1.4">
139146
The `dependency-fetch-output-from-state` experiment only works for S3 backends. If you are using a different backend, this experiment won't do anything.
147+
</Before>
148+
149+
<Since version="1.1.4">
150+
The experiment supports S3 and GCS backends. Azure Storage (`azurerm`) is supported when the [`azure-backend`](/reference/experiments/active#azure-backend) experiment is also enabled. Unsupported backends, and supported backends whose configuration the direct reader cannot reproduce, fall back to the normal OpenTofu/Terraform output command.
151+
</Since>
140152

141153
</Card>
142154

@@ -148,7 +160,7 @@ There is no guarantee that OpenTofu/Terraform will maintain the existing schema
148160

149161
<Card title="Incompatible with OpenTofu state encryption" icon="error">
150162

151-
When client-side state encryption is enabled, the state file in S3 is encrypted before upload and cannot be parsed directly by Terragrunt, resulting in a hard failure. If you encounter JSON parsing errors when using this experiment, check whether you have OpenTofu state encryption enabled and disable the experiment with `--no-dependency-fetch-output-from-state` if so.
163+
When client-side state encryption is enabled, the state file is encrypted before upload and cannot be parsed directly by Terragrunt, resulting in a hard failure. If you encounter JSON parsing errors when using this experiment, check whether you have OpenTofu state encryption enabled and disable the experiment with `--no-dependency-fetch-output-from-state` if so.
152164

153165
</Card>
154166

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
version: "v1.1.4"
3+
category: "experiments-updated"
4+
---
5+
6+
#### Read dependency outputs directly from Azure state
7+
8+
The `dependency-fetch-output-from-state` experiment can now read dependency outputs directly from Azure Storage (`azurerm`) state, in addition to S3. This avoids initializing the dependency and running `tofu output` or `terraform output`.
9+
10+
Azure direct reads require the `azure-backend` experiment as well. Unsupported configurations requiring native-only authentication, endpoint, timeout, or customer-provided-key behavior continue to use the native output path.
11+
12+
When a dependency has no state yet, Terragrunt uses that dependency block's `mock_outputs`, as it already does for S3. When Azure direct reads resolve a storage account key through Azure Resource Manager, which is the case unless `access_key`, `sas_token`, or `use_azuread_auth` is set, a `resource_group_name`, `storage_account_name`, or `subscription_id` naming a resource that does not exist fails with an error naming those keys rather than substituting mock outputs.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
version: "v1.1.4"
3+
category: "experiments-updated"
4+
---
5+
6+
#### Read dependency outputs directly from GCS state
7+
8+
The `dependency-fetch-output-from-state` experiment can now read dependency outputs directly from GCS state, in addition to S3. This avoids initializing the dependency and running `tofu output` or `terraform output`.
9+
10+
Unsupported GCS configurations continue to use the native output path. When a dependency has no state yet, Terragrunt uses that dependency block's `mock_outputs`, as it already does for S3.
11+
12+
Thanks to [@joshmyers](https://github.com/joshmyers) for the original GCS implementation.

docs/src/data/experiments/azure-backend.mdx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,17 @@ Authentication supports six methods, resolved in the following order:
5454
Government, and China clouds are supported via the `environment` key.
5555

5656
Without the experiment enabled, these lifecycle operations return an error naming
57-
the experiment; reading and writing the state itself is always handled by the
58-
native OpenTofu/Terraform `azurerm` backend. Direct state file reads for
57+
the experiment; normal state reading and writing is handled by the native
58+
OpenTofu/Terraform `azurerm` backend.
59+
60+
When both this experiment and
5961
[`dependency-fetch-output-from-state`](/reference/experiments/active#dependency-fetch-output-from-state)
60-
are not implemented yet.
62+
are enabled, Terragrunt can read dependency outputs directly from the Azure state
63+
blob without initializing the dependency or running `tofu output`/`terraform output`.
64+
State protected with `customer_provided_key`, and configurations that rely on
65+
native-only authentication, `metadata_host`, or `timeout_seconds`, continue through
66+
the native backend path. This preserves the backend's identity, endpoint, and
67+
decryption behavior.
6168

6269
See the [Azure Storage backend documentation](/features/units/state-backend#azure-storage-azurerm-backend)
6370
for configuration keys and known limitations.
@@ -89,8 +96,8 @@ To transition the `azure-backend` feature to a stable release, the following mus
8996
- [x] Bootstrap of storage accounts and blob containers, including versioning and soft delete convergence.
9097
- [ ] Optional RBAC role assignment for `use_azuread_auth` during bootstrap (the data-plane role must currently be granted manually).
9198
- [x] Delete operations for state blobs and containers, with confirmation prompts, and state migration within a storage account.
92-
- [ ] Direct state file reads from Azure blobs for `--dependency-fetch-output-from-state`.
99+
- [x] Direct state file reads from Azure blobs for `--dependency-fetch-output-from-state`.
93100
- [x] Documentation covering authentication methods, configuration keys, and troubleshooting.
94-
- [x] End-to-end live coverage against a real subscription for container bootstrap, blob versioning convergence, and backend delete, behind the `azure` build tag.
101+
- [x] End-to-end live coverage against a real subscription for container bootstrap, blob versioning convergence, backend delete, and direct dependency state reads, behind the `azure` build tag.
95102
- [ ] End-to-end live coverage for resource group and storage account creation, soft-delete retention convergence, and state migration. The current live tests assume a pre-existing storage account.
96103
- [ ] Community feedback on real-world usage.

docs/src/data/experiments/dependency-fetch-output-from-state.mdx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ By default, Terragrunt retrieves dependency outputs by running `tofu output` or
99

1010
**Current Backend Support:**
1111

12-
- S3 backend: Fully supported
12+
- S3 and GCS backends: Direct state reads are supported
13+
- Azure Storage (`azurerm`) backend: Direct state reads are supported when the [`azure-backend`](/reference/experiments/active#azure-backend) experiment is also enabled
1314
- Other backends: Falls back to the normal method (using `tofu/terraform output`)
1415

15-
When an unsupported backend is encountered, Terragrunt will automatically fall back to the default method of using `tofu/terraform output`.
16+
Azure state protected with `customer_provided_key`, and Azure configurations that rely on native-only authentication, `metadata_host`, or `timeout_seconds`, also use the normal method.
17+
18+
GCS configurations that rely on backend-only credential environment variables, inline credentials or relative credential-file paths, service-account impersonation, custom storage endpoints, custom universe domains, or competing credential sources with different precedence also use the normal method. This preserves the native backend's authentication and endpoint behavior.
1619

1720
**Known Limitations:**
1821

19-
This experiment is **not compatible with OpenTofu state encryption**. When OpenTofu's [client-side state encryption](https://opentofu.org/docs/language/state/encryption/) is enabled, the state file stored in S3 is encrypted before upload. Since this experiment reads the raw state file directly from S3 via the AWS SDK, it cannot decrypt the state and will fail with a JSON parsing error. If you are using OpenTofu state encryption, you must disable this experiment using the `--no-dependency-fetch-output-from-state` flag.
22+
This experiment is **not compatible with OpenTofu state encryption**. When OpenTofu's [client-side state encryption](https://opentofu.org/docs/language/state/encryption/) is enabled, the state file is encrypted before upload. Since this experiment reads the raw state object directly through the backend's cloud storage API, it cannot decrypt the state and will fail with a JSON parsing error. If you are using OpenTofu state encryption, you must disable this experiment using the `--no-dependency-fetch-output-from-state` flag.
2023

2124
**Disabling the feature:**
2225

@@ -36,8 +39,9 @@ Provide your feedback in the dedicated [GitHub discussion](https://github.com/gr
3639
### `dependency-fetch-output-from-state` - Criteria for stabilization
3740
To transition the `dependency-fetch-output-from-state` feature to a stable release, the following must be addressed, at a minimum:
3841

39-
- [ ] Add support for additional backends (e.g., GCS, etc.)
40-
- [ ] Comprehensive integration testing across different backend types
42+
- [x] Add support for additional backends (GCS and Azure Storage)
43+
- [x] Live direct-state-read integration coverage for S3, GCS, and Azure Storage
44+
- [ ] Comprehensive integration testing across backend authentication, encryption, workspace, and error scenarios
4145
- [ ] Performance benchmarking to validate speed improvements
4246
- [ ] Error handling and edge case testing
4347
- [x] Documentation of supported backends and limitations

docs/src/data/faq/why-is-terragrunt-slow.mdx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ description: "Run fewer units with --filter, share provider downloads with the P
44
order: 7
55
---
66

7+
import Before from '@components/Before.astro';
8+
import Since from '@components/Since.astro';
9+
710
Most slow runs come down to doing work you did not need to do: running units that did not change, downloading the same provider once per unit, or initializing dependencies just to read their outputs. The [Performance](/troubleshooting/performance/) guide covers this in full. The short version:
811

912
## Run fewer units
@@ -36,7 +39,15 @@ By default, Terragrunt runs `output -json` against each dependency, which loads
3639
terragrunt run --all --experiment=dependency-fetch-output-from-state -- plan
3740
```
3841

39-
This only applies to S3 backends, and it fails outright with OpenTofu client-side state encryption, since Terragrunt cannot parse an encrypted state file. See [the gotchas](/troubleshooting/performance/#fetching-output-from-state---gotchas) before turning it on.
42+
<Before version="1.1.4">
43+
This only applies to S3 backends.
44+
</Before>
45+
46+
<Since version="1.1.4">
47+
This applies to S3 and GCS backends. Azure Storage (`azurerm`) also supports it when the `azure-backend` experiment is enabled.
48+
</Since>
49+
50+
It fails outright with OpenTofu client-side state encryption, since Terragrunt cannot parse an encrypted state file. See [the gotchas](/troubleshooting/performance/#fetching-output-from-state---gotchas) before turning it on.
4051

4152
## Cache repository clones
4253

docs/src/data/flags/dependency-fetch-output-from-state.mdx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,31 @@ env:
88
---
99

1010
import { Aside } from '@astrojs/starlight/components';
11+
import Before from '@components/Before.astro';
12+
import Since from '@components/Since.astro';
1113

12-
This flag modifies how Terragrunt retrieves output values from dependent units. When enabled, Terragrunt will read the outputs directly from the state file instead of running `terraform output` or `tofu output`.
14+
This flag modifies how Terragrunt retrieves output values from dependent units. When enabled, Terragrunt will read the outputs directly from the state file instead of running `tofu output` or `terraform output`.
1315

1416
<Aside type="note">
1517
This flag is equivalent to enabling the `dependency-fetch-output-from-state` experiment. You can also enable this feature using `--experiment dependency-fetch-output-from-state` or `--experiment-mode`. For more information, see the [Experiments documentation](/reference/experiments/active#dependency-fetch-output-from-state).
1618
</Aside>
1719

1820
The main benefit this flag provides is performance. Reading directly from state is typically faster than executing the OpenTofu/Terraform binary to get the same outputs.
1921

20-
The limitation of this approach is that it is only supported by the S3 backend, and OpenTofu/Terraform may change the schema of the state file in the future, breaking this functionality.
22+
<Before version="1.1.4">
23+
This approach is only supported by the S3 backend.
24+
</Before>
25+
26+
<Since version="1.1.4">
27+
This approach supports S3 and GCS backends. It also supports the Azure Storage (`azurerm`) backend when the [`azure-backend`](/reference/experiments/active#azure-backend) experiment is enabled. Other backends continue to use `tofu output` or `terraform output`.
28+
29+
Terragrunt also uses the native output path for Azure state protected by `customer_provided_key`, Azure configurations requiring native-only authentication or endpoint behavior, and GCS configurations whose backend-specific credential or endpoint behavior is not yet mirrored by the direct reader.
30+
</Since>
31+
32+
OpenTofu/Terraform may change the schema of the state file in the future, breaking this functionality.
2133

2234
<Aside type="caution">
23-
This flag is **not compatible with OpenTofu state encryption**. When OpenTofu's client-side state encryption is enabled, the state file stored in S3 is encrypted before upload. Since this flag causes Terragrunt to read the raw state file directly from S3 via the AWS SDK, it cannot decrypt the state and will fail with a JSON parsing error. If you are using OpenTofu state encryption, disable this flag with `--no-dependency-fetch-output-from-state`.
35+
This flag is **not compatible with OpenTofu state encryption**. When OpenTofu's client-side state encryption is enabled, the state file is encrypted before upload. Since this flag causes Terragrunt to read the raw state object directly through the backend's cloud storage API, it cannot decrypt the state and will fail with a JSON parsing error. If you are using OpenTofu state encryption, disable this flag with `--no-dependency-fetch-output-from-state`.
2436
</Aside>
2537

2638
<Aside type="caution">

0 commit comments

Comments
 (0)