@intentius/chant-lexicon-terraform 0.124.51 → 0.124.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/__fixtures__/pr-loop/estate.component.d.ts +7 -0
- package/dist/__fixtures__/pr-loop/estate.component.d.ts.map +1 -0
- package/dist/__fixtures__/pr-loop/estate.component.js +7 -0
- package/dist/__fixtures__/report/generate.d.ts +26 -0
- package/dist/__fixtures__/report/generate.d.ts.map +1 -0
- package/dist/__fixtures__/report/generate.js +58 -0
- package/dist/applied-state.d.ts +27 -0
- package/dist/applied-state.d.ts.map +1 -0
- package/dist/applied-state.js +44 -0
- package/dist/backend-config.d.ts +53 -0
- package/dist/backend-config.d.ts.map +1 -0
- package/dist/backend-config.js +136 -0
- package/dist/behaviour/kinds.d.ts.map +1 -1
- package/dist/behaviour/kinds.js +4 -0
- package/dist/behaviour/predict.d.ts.map +1 -1
- package/dist/behaviour/predict.js +6 -2
- package/dist/behaviour/reference-catalog.d.ts +16 -5
- package/dist/behaviour/reference-catalog.d.ts.map +1 -1
- package/dist/behaviour/reference-catalog.js +16 -5
- package/dist/behaviour/request.d.ts.map +1 -1
- package/dist/behaviour/request.js +3 -2
- package/dist/changed-roots.d.ts +6 -4
- package/dist/changed-roots.d.ts.map +1 -1
- package/dist/changed-roots.js +14 -18
- package/dist/commands.d.ts +5 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +87 -4
- package/dist/components/capability-plugin.d.ts +65 -3
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability-plugin.js +197 -13
- package/dist/components/compose-group.d.ts +145 -0
- package/dist/components/compose-group.d.ts.map +1 -0
- package/dist/components/compose-group.js +407 -0
- package/dist/components/placeholder-preview.d.ts +78 -0
- package/dist/components/placeholder-preview.d.ts.map +1 -0
- package/dist/components/placeholder-preview.js +254 -0
- package/dist/compose/apply-events.d.ts +46 -0
- package/dist/compose/apply-events.d.ts.map +1 -0
- package/dist/compose/apply-events.js +77 -0
- package/dist/compose/estate.d.ts +194 -0
- package/dist/compose/estate.d.ts.map +1 -0
- package/dist/compose/estate.js +363 -0
- package/dist/compose/hcl.d.ts +99 -0
- package/dist/compose/hcl.d.ts.map +1 -0
- package/dist/compose/hcl.js +302 -0
- package/dist/compose/module-address.d.ts +24 -0
- package/dist/compose/module-address.d.ts.map +1 -0
- package/dist/compose/module-address.js +43 -0
- package/dist/compose/root.d.ts +127 -0
- package/dist/compose/root.d.ts.map +1 -0
- package/dist/compose/root.js +586 -0
- package/dist/compose/run.d.ts +183 -0
- package/dist/compose/run.d.ts.map +1 -0
- package/dist/compose/run.js +447 -0
- package/dist/compose/slice.d.ts +102 -0
- package/dist/compose/slice.d.ts.map +1 -0
- package/dist/compose/slice.js +249 -0
- package/dist/compose/state-address.d.ts +28 -0
- package/dist/compose/state-address.d.ts.map +1 -0
- package/dist/compose/state-address.js +154 -0
- package/dist/compose/state-merge.d.ts +52 -0
- package/dist/compose/state-merge.d.ts.map +1 -0
- package/dist/compose/state-merge.js +135 -0
- package/dist/compose.d.ts +179 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +482 -0
- package/dist/composites/terraform-apply-op.d.ts.map +1 -1
- package/dist/composites/terraform-apply-op.js +7 -3
- package/dist/config.d.ts +59 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -9
- package/dist/describe-resources.d.ts +74 -12
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/describe-resources.js +374 -66
- package/dist/drift-read.d.ts +33 -0
- package/dist/drift-read.d.ts.map +1 -0
- package/dist/drift-read.js +243 -0
- package/dist/drift-record.d.ts +147 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +383 -0
- package/dist/hcl/edges.d.ts.map +1 -1
- package/dist/hcl/edges.js +24 -1
- package/dist/hcl/files.d.ts +61 -0
- package/dist/hcl/files.d.ts.map +1 -0
- package/dist/hcl/files.js +221 -0
- package/dist/hcl/instances.d.ts +82 -0
- package/dist/hcl/instances.d.ts.map +1 -0
- package/dist/hcl/instances.js +390 -0
- package/dist/hcl/parse.d.ts +81 -9
- package/dist/hcl/parse.d.ts.map +1 -1
- package/dist/hcl/parse.js +114 -16
- package/dist/hcl/roots.d.ts.map +1 -1
- package/dist/hcl/roots.js +5 -0
- package/dist/hcl/suppressions.d.ts.map +1 -1
- package/dist/hcl/suppressions.js +8 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -2
- package/dist/integrity.json +3 -3
- package/dist/live-plan-reasons.d.ts +21 -0
- package/dist/live-plan-reasons.d.ts.map +1 -0
- package/dist/live-plan-reasons.js +47 -0
- package/dist/lsp/option-keys.d.ts.map +1 -1
- package/dist/lsp/option-keys.js +2 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/index.d.ts +6 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +5 -1
- package/dist/op/activities/live-detect.d.ts +4 -3
- package/dist/op/activities/live-detect.d.ts.map +1 -1
- package/dist/op/activities/live-detect.js +57 -32
- package/dist/op/activities/pin-rollout.d.ts +2 -0
- package/dist/op/activities/pin-rollout.d.ts.map +1 -1
- package/dist/op/activities/pin-rollout.js +1 -0
- package/dist/op/activities/terraform.d.ts +153 -5
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/activities/terraform.js +205 -20
- package/dist/op/activity-contracts.d.ts +27 -0
- package/dist/op/activity-contracts.d.ts.map +1 -1
- package/dist/op/activity-contracts.js +19 -1
- package/dist/op/builders.d.ts +7 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -0
- package/dist/pin/edit.d.ts.map +1 -1
- package/dist/pin/edit.js +35 -0
- package/dist/pin/rollout.d.ts +2 -0
- package/dist/pin/rollout.d.ts.map +1 -1
- package/dist/pin/rollout.js +14 -11
- package/dist/plan-shape.d.ts +30 -0
- package/dist/plan-shape.d.ts.map +1 -0
- package/dist/plan-shape.js +125 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +32 -18
- package/dist/report.d.ts +216 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +666 -0
- package/dist/skills/chant-terraform.md +1 -1
- package/dist/state/azure-blob.d.ts +68 -0
- package/dist/state/azure-blob.d.ts.map +1 -0
- package/dist/state/azure-blob.js +201 -0
- package/dist/state/backend.d.ts +158 -0
- package/dist/state/backend.d.ts.map +1 -0
- package/dist/state/backend.js +406 -0
- package/dist/state/exec.d.ts +39 -0
- package/dist/state/exec.d.ts.map +1 -0
- package/dist/state/exec.js +80 -0
- package/dist/state/gcs.d.ts +62 -0
- package/dist/state/gcs.d.ts.map +1 -0
- package/dist/state/gcs.js +224 -0
- package/dist/state/index.d.ts +15 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +14 -0
- package/dist/state/locks.d.ts +105 -0
- package/dist/state/locks.d.ts.map +1 -0
- package/dist/state/locks.js +130 -0
- package/dist/state/object-store.d.ts +37 -0
- package/dist/state/object-store.d.ts.map +1 -0
- package/dist/state/object-store.js +20 -0
- package/dist/state/root-states.d.ts +131 -0
- package/dist/state/root-states.d.ts.map +1 -0
- package/dist/state/root-states.js +241 -0
- package/dist/state/s3.d.ts +68 -0
- package/dist/state/s3.d.ts.map +1 -0
- package/dist/state/s3.js +170 -0
- package/dist/state/store.d.ts +51 -0
- package/dist/state/store.d.ts.map +1 -0
- package/dist/state/store.js +185 -0
- package/dist/terragrunt/affected.d.ts.map +1 -1
- package/dist/terragrunt/affected.js +2 -1
- package/package.json +7 -3
- package/src/__fixtures__/ACCEPTANCE.md +69 -7
- package/src/__fixtures__/compose/apply-failed-in-app.jsonl +12 -0
- package/src/__fixtures__/compose/state-app.json +66 -0
- package/src/__fixtures__/compose/state-edge.json +40 -0
- package/src/__fixtures__/compose/state-net.json +58 -0
- package/src/__fixtures__/compose/three-app.plan.json +184 -0
- package/src/__fixtures__/compose/three-composed.plan.json +509 -0
- package/src/__fixtures__/compose/three-edge.plan.json +144 -0
- package/src/__fixtures__/compose/three-net.plan.json +174 -0
- package/src/__fixtures__/compose/unknown-composed.plan.json +228 -0
- package/src/__fixtures__/compose/working-after-apply.json +145 -0
- package/src/__fixtures__/config-blocks/app/main.tf +61 -0
- package/src/__fixtures__/config-blocks/app/modules/network/main.tf +4 -0
- package/src/__fixtures__/config-blocks/app-json/main.tf.json +39 -0
- package/src/__fixtures__/config-files/shadow/main.tf +3 -0
- package/src/__fixtures__/config-files/shadow/main.tofu +3 -0
- package/src/__fixtures__/config-files/shadow/other.tf +3 -0
- package/src/__fixtures__/config-files/tf/main.tf +11 -0
- package/src/__fixtures__/config-files/tf-json/main.tf.json +18 -0
- package/src/__fixtures__/config-files/tofu/main.tofu +11 -0
- package/src/__fixtures__/config-files/tofu-json/main.tofu.json +18 -0
- package/src/__fixtures__/config-files/tofu-only/main.tofu +3 -0
- package/src/__fixtures__/drift-record/README.md +11 -0
- package/src/__fixtures__/drift-record/live-plan-sections.json +27 -0
- package/src/__fixtures__/instance-forms/app/main.tf +110 -0
- package/src/__fixtures__/instance-forms/app/modules/svc/main.tf +3 -0
- package/src/__fixtures__/instance-vars/app/main.tf +52 -0
- package/src/__fixtures__/instance-vars/app/modules/app/main.tf +12 -0
- package/src/__fixtures__/instance-vars/app/modules/edge/main.tf +3 -0
- package/src/__fixtures__/instance-vars/app/terraform.tfvars +1 -0
- package/src/__fixtures__/live-module-keyed/live-graph.json +259 -0
- package/src/__fixtures__/live-module-keyed/live-plan.json +87 -0
- package/src/__fixtures__/live-module-keyed/root/estate.chdf.hcl +1 -0
- package/src/__fixtures__/live-module-keyed/root/main.tf +21 -0
- package/src/__fixtures__/live-module-keyed/root/modules/app/main.tf +17 -0
- package/src/__fixtures__/live-module-keyed/root/modules/edge/main.tf +7 -0
- package/src/__fixtures__/live-module-keyed/root/versions.tf +30 -0
- package/src/__fixtures__/live-module-keyed/show-state.json +146 -0
- package/src/__fixtures__/pr-loop/README.md +50 -0
- package/src/__fixtures__/pr-loop/chant.config.json +13 -0
- package/src/__fixtures__/pr-loop/estate.component.ts +10 -0
- package/src/__fixtures__/pr-loop/roots/a/main.tf +11 -0
- package/src/__fixtures__/pr-loop/roots/app/main.tf +19 -0
- package/src/__fixtures__/pr-loop/roots/b/main.tf +7 -0
- package/src/__fixtures__/pr-loop/roots/dns/main.tf +3 -0
- package/src/__fixtures__/pr-loop/roots/net/main.tf +7 -0
- package/src/__fixtures__/report/applied.show.json +51 -0
- package/src/__fixtures__/report/generate.ts +63 -0
- package/src/__fixtures__/report/plan.show.json +200 -0
- package/src/__fixtures__/report/tf-apply/change-set.json +170 -0
- package/src/__fixtures__/report/tf-apply/report.json +338 -0
- package/src/__fixtures__/report/tf-plan/change-set.json +170 -0
- package/src/__fixtures__/report/tf-plan/report.json +320 -0
- package/src/__fixtures__/three-cloud-azure.graph.json +290 -0
- package/src/applied-state.ts +52 -0
- package/src/backend-config.test.ts +105 -0
- package/src/backend-config.ts +133 -0
- package/src/behaviour/kinds.ts +4 -0
- package/src/behaviour/predict.ts +5 -2
- package/src/behaviour/reference-catalog.plugin.test.ts +65 -0
- package/src/behaviour/reference-catalog.ts +16 -5
- package/src/behaviour/request.ts +3 -2
- package/src/change-set-instances.test.ts +98 -0
- package/src/changed-roots.ts +14 -16
- package/src/commands.ts +84 -4
- package/src/components/capability-plugin.test.ts +172 -5
- package/src/components/capability-plugin.ts +212 -11
- package/src/components/change-set-graph.e2e.test.ts +11 -5
- package/src/components/compose-group.test.ts +486 -0
- package/src/components/compose-group.ts +489 -0
- package/src/components/demo-composed-roots.e2e.test.ts +440 -0
- package/src/components/member-outputs.test.ts +76 -0
- package/src/components/placeholder-preview.test.ts +147 -0
- package/src/components/placeholder-preview.ts +257 -0
- package/src/components/pr-loop-compose.tofu.e2e.test.ts +363 -0
- package/src/components/pr-loop.tofu.test.ts +112 -56
- package/src/compose/apply-events.test.ts +62 -0
- package/src/compose/apply-events.ts +100 -0
- package/src/compose/estate.choudoufu.e2e.test.ts +112 -0
- package/src/compose/estate.test.ts +421 -0
- package/src/compose/estate.ts +443 -0
- package/src/compose/hcl.ts +311 -0
- package/src/compose/module-address.ts +49 -0
- package/src/compose/root.test.ts +416 -0
- package/src/compose/root.ts +592 -0
- package/src/compose/run.test.ts +440 -0
- package/src/compose/run.tofu.test.ts +176 -0
- package/src/compose/run.ts +527 -0
- package/src/compose/slice.test.ts +184 -0
- package/src/compose/slice.ts +290 -0
- package/src/compose/state-address.ts +157 -0
- package/src/compose/state-merge.test.ts +131 -0
- package/src/compose/state-merge.ts +148 -0
- package/src/compose.test.ts +248 -0
- package/src/compose.ts +627 -0
- package/src/composites/terraform-apply-op.test.ts +9 -0
- package/src/composites/terraform-apply-op.ts +7 -3
- package/src/composites/terraform-pin-rollout-op.test.ts +2 -2
- package/src/config-file-listers.test.ts +265 -0
- package/src/config.ts +44 -9
- package/src/describe-resources.engine-facts.test.ts +412 -0
- package/src/describe-resources.live-module-keyed.test.ts +290 -0
- package/src/describe-resources.ts +416 -70
- package/src/drift-read.ts +284 -0
- package/src/drift-record.test.ts +223 -0
- package/src/drift-record.ts +455 -0
- package/src/hcl/config-blocks.test.ts +174 -0
- package/src/hcl/edges.ts +21 -1
- package/src/hcl/files.ts +234 -0
- package/src/hcl/instance-forms.test.ts +94 -0
- package/src/hcl/instances.test.ts +137 -0
- package/src/hcl/instances.ts +422 -0
- package/src/hcl/parse.test.ts +139 -1
- package/src/hcl/parse.ts +149 -16
- package/src/hcl/roots.ts +6 -0
- package/src/hcl/suppressions.ts +8 -2
- package/src/index.ts +76 -0
- package/src/live-plan-reasons.ts +54 -0
- package/src/lsp/completions.test.ts +1 -1
- package/src/lsp/option-keys.ts +2 -0
- package/src/op/activities/choudoufu-plan-set-op.test.ts +111 -0
- package/src/op/activities/index.ts +9 -0
- package/src/op/activities/live-detect.ts +55 -26
- package/src/op/activities/pin-rollout.ts +3 -0
- package/src/op/activities/registry.test.ts +2 -1
- package/src/op/activities/terraform.test.ts +55 -0
- package/src/op/activities/terraform.ts +266 -22
- package/src/op/activity-contracts.test.ts +1 -0
- package/src/op/activity-contracts.ts +24 -1
- package/src/op/builders.ts +14 -0
- package/src/pin/bundle.test.ts +2 -0
- package/src/pin/edit.ts +30 -0
- package/src/pin/rollout.ts +16 -11
- package/src/plan-shape.test.ts +148 -0
- package/src/plan-shape.ts +128 -0
- package/src/plugin.ts +33 -19
- package/src/report.test.ts +423 -0
- package/src/report.ts +752 -0
- package/src/signal-only-root.test.ts +72 -0
- package/src/skills/chant-terraform.md +1 -1
- package/src/state/azure-blob.ts +223 -0
- package/src/state/backend-verdict.test.ts +187 -0
- package/src/state/backend.test.ts +127 -0
- package/src/state/backend.ts +488 -0
- package/src/state/exec.ts +111 -0
- package/src/state/gcs.ts +254 -0
- package/src/state/index.ts +15 -0
- package/src/state/locks.test.ts +84 -0
- package/src/state/locks.ts +201 -0
- package/src/state/object-store.ts +35 -0
- package/src/state/root-states-floci.e2e.test.ts +66 -0
- package/src/state/root-states.test.ts +462 -0
- package/src/state/root-states.ts +309 -0
- package/src/state/s3.ts +193 -0
- package/src/state/store.ts +225 -0
- package/src/terragrunt/affected.ts +2 -1
- package/src/workspace-kinds.test.ts +4 -17
- package/workspace-kinds.json +1 -24
- package/dist/workspace-member.d.ts +0 -30
- package/dist/workspace-member.d.ts.map +0 -1
- package/dist/workspace-member.js +0 -91
- package/schemas/pulumi.schema.json +0 -34
- package/src/testdata/pulumi-member/Pulumi.yaml +0 -2
- package/src/testdata/pulumi-member/stack-export.json +0 -53
- package/src/testdata/pulumi-unexported/Pulumi.yaml +0 -2
- package/src/workspace-member.test.ts +0 -89
- package/src/workspace-member.ts +0 -126
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-keyed addresses through describe-resources.ts, from documents
|
|
3
|
+
* (chant #4513).
|
|
4
|
+
*
|
|
5
|
+
* #4488 gave live instances under an expanded module call a `scope`, and its
|
|
6
|
+
* core test (packages/core/src/graph-ir-live.test.ts) feeds that metadata in
|
|
7
|
+
* by hand. This file reads it out of a live-plan document and a state
|
|
8
|
+
* document whose every address is module-keyed (`module.app[0].aws_eip.pool[1]`,
|
|
9
|
+
* `module.edge["east"]...`), then checks that the live graph's instance ids
|
|
10
|
+
* are the ones the declared graph lists.
|
|
11
|
+
*
|
|
12
|
+
* The declared side is real: `src/__fixtures__/live-module-keyed/root/`,
|
|
13
|
+
* rendered as `buildRoots()` renders it, with an `estate.chdf.hcl` sidecar
|
|
14
|
+
* that makes the root live under `binary: "choudoufu"`.
|
|
15
|
+
*
|
|
16
|
+
* The two documents were built by hand. No binary was run, so these are not
|
|
17
|
+
* recordings like `live-plan-depth/`. Where each part comes from, all read
|
|
18
|
+
* on choudoufu `origin/integration/consolidation-graph` (b47315e7c):
|
|
19
|
+
*
|
|
20
|
+
* - `live-plan.json`'s keys and their order: `LivePlanDocument`,
|
|
21
|
+
* `LivePlanBound`, `LiveOmission` and `LiveUnowned` in
|
|
22
|
+
* internal/command/views/live_plan.go. The addresses are
|
|
23
|
+
* `addrs.AbsResourceInstance.String()`, which `liveBoundReport`,
|
|
24
|
+
* `liveOmissions` and `liveUnownedReport` in internal/command/live_plan.go
|
|
25
|
+
* write as `addr`.
|
|
26
|
+
* - `source`: `derived` for the log group, whose name is its identity;
|
|
27
|
+
* `marker` for the EIPs, whose allocation id EC2 assigns
|
|
28
|
+
* (`liveBoundReport`'s switch, the same split as the recorded
|
|
29
|
+
* `live-plan-depth/live-plan.json`).
|
|
30
|
+
* - `adopt_tofu_address`: `markers.EscapeAddress`
|
|
31
|
+
* (internal/live/markers/markers.go) and the escaping table in
|
|
32
|
+
* live/MARKERS.md, `module.subnets["a"].aws_subnet.this` ->
|
|
33
|
+
* `module.subnets:a.aws_subnet.this`.
|
|
34
|
+
* - The omission `detail` strings: the ABSENT template in
|
|
35
|
+
* internal/live/projection/build.go, the no-marker UNOWNED template and
|
|
36
|
+
* `anotherEstateDetail` in internal/live/projection/ownership.go. The
|
|
37
|
+
* paired "Live resource outside this estate" diagnostics, and
|
|
38
|
+
* `upstream_version`, follow the recorded v0.30.0 document in
|
|
39
|
+
* `live-plan-depth/`. `choudoufu_version` is empty, which the struct
|
|
40
|
+
* documents as a development build, because no release produced this
|
|
41
|
+
* document.
|
|
42
|
+
* - That a module call's count or for_each reaches a child's identity
|
|
43
|
+
* through a variable: `TestModuleCallCountVar` and `TestModuleCallForEachVar`
|
|
44
|
+
* in internal/live/identity/moduleforeachvar_test.go.
|
|
45
|
+
* - `show-state.json`: `jsonstate.Module` and `jsonstate.Resource` in
|
|
46
|
+
* internal/command/jsonstate/state.go. A child module's `address` is
|
|
47
|
+
* `addrs.ModuleInstance.String()` (`module.app[0]`, `marshalModules`), and
|
|
48
|
+
* a resource's address carries the module prefix, as the recorded
|
|
49
|
+
* `src/__fixtures__/show-state.json` does for an unkeyed call.
|
|
50
|
+
* - The EIP allocation ids and the account id in the ARNs are made up.
|
|
51
|
+
*
|
|
52
|
+
* Nothing here runs choudoufu or tofu: the activities are injected.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
import { readFileSync } from "node:fs";
|
|
56
|
+
import { dirname, join } from "node:path";
|
|
57
|
+
import { fileURLToPath } from "node:url";
|
|
58
|
+
import { describe, expect, it } from "vitest";
|
|
59
|
+
import { normalizeObservation } from "@intentius/chant/observation";
|
|
60
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
61
|
+
import { buildGraphIr, buildLiveGraphIr, overlayGraphs, withInstanceNodes } from "@intentius/chant/graph-ir";
|
|
62
|
+
import { describeResources, indexLivePlan, indexStateResources, type TerraformReadDeps } from "./describe-resources";
|
|
63
|
+
import { renderTerraformRoots } from "./hcl/roots";
|
|
64
|
+
|
|
65
|
+
const fixtures = join(dirname(fileURLToPath(import.meta.url)), "__fixtures__");
|
|
66
|
+
const FIXTURE = join(fixtures, "live-module-keyed");
|
|
67
|
+
const ROOT_DIR = join(FIXTURE, "root");
|
|
68
|
+
const LIVE_PLAN: unknown = JSON.parse(readFileSync(join(FIXTURE, "live-plan.json"), "utf-8"));
|
|
69
|
+
const STATE: unknown = JSON.parse(readFileSync(join(FIXTURE, "show-state.json"), "utf-8"));
|
|
70
|
+
const ESTATE = "module-keyed-estate";
|
|
71
|
+
|
|
72
|
+
type Entities = Map<string, { entityType: string; props: Record<string, unknown> }>;
|
|
73
|
+
|
|
74
|
+
/** The fixture root rendered under `binary`: `"choudoufu"` makes it live, `"tofu"` stock. */
|
|
75
|
+
async function render(binary: "choudoufu" | "tofu"): Promise<{ declarables: Map<string, Declarable>; entities: Entities }> {
|
|
76
|
+
const { entities: declarables } = await renderTerraformRoots({
|
|
77
|
+
projectRoot: FIXTURE,
|
|
78
|
+
roots: { estate: { dir: "./root" } },
|
|
79
|
+
binary,
|
|
80
|
+
});
|
|
81
|
+
const entities: Entities = new Map();
|
|
82
|
+
for (const [key, entity] of declarables) {
|
|
83
|
+
entities.set(key, { entityType: entity.entityType, props: (entity as Declarable & { props: Record<string, unknown> }).props });
|
|
84
|
+
}
|
|
85
|
+
return { declarables, entities };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function options(entities: Entities) {
|
|
89
|
+
return { environment: "prod", buildOutput: "", entityNames: [...entities.keys()].sort(), entities };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const never = ((args: { root: string }) => {
|
|
93
|
+
throw new Error(`unexpected activity for root "${args.root}"`);
|
|
94
|
+
}) as never;
|
|
95
|
+
|
|
96
|
+
/** The live root's activities: `live-plan -json` answers, nothing else may run. */
|
|
97
|
+
function liveDeps(): TerraformReadDeps {
|
|
98
|
+
return {
|
|
99
|
+
init: never,
|
|
100
|
+
show: never,
|
|
101
|
+
liveLs: never,
|
|
102
|
+
livePlan: (async () => ({ json: LIVE_PLAN, dir: ROOT_DIR, estate: ESTATE })) as unknown as TerraformReadDeps["livePlan"],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** The stock root's activities: `init`, then `show -json` over the state document. */
|
|
107
|
+
function stateDeps(): TerraformReadDeps {
|
|
108
|
+
return {
|
|
109
|
+
init: (async () => ({ dir: ROOT_DIR })) as TerraformReadDeps["init"],
|
|
110
|
+
show: (async () => ({ source: "state" as const, json: STATE, text: "", dir: ROOT_DIR, adds: 0, changes: 0, destroys: 0 })) as TerraformReadDeps["show"],
|
|
111
|
+
livePlan: never,
|
|
112
|
+
liveLs: never,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const POOL = [
|
|
117
|
+
"module.app[0].aws_eip.pool[0]",
|
|
118
|
+
"module.app[0].aws_eip.pool[1]",
|
|
119
|
+
"module.app[1].aws_eip.pool[0]",
|
|
120
|
+
"module.app[1].aws_eip.pool[1]",
|
|
121
|
+
];
|
|
122
|
+
const EAST = 'module.edge["east"].aws_cloudwatch_log_group.front';
|
|
123
|
+
const WEST = 'module.edge["west"].aws_cloudwatch_log_group.front';
|
|
124
|
+
|
|
125
|
+
describe("the module-keyed fixture root (#4513)", () => {
|
|
126
|
+
it("declares each block once, under its unkeyed module call, and live", async () => {
|
|
127
|
+
const { entities } = await render("choudoufu");
|
|
128
|
+
for (const key of [
|
|
129
|
+
"estate/module.app",
|
|
130
|
+
"estate/module.edge",
|
|
131
|
+
"estate/module.app/aws_eip.pool",
|
|
132
|
+
"estate/module.app/aws_cloudwatch_log_group.logs",
|
|
133
|
+
"estate/module.edge/aws_cloudwatch_log_group.front",
|
|
134
|
+
]) {
|
|
135
|
+
expect(entities.has(key), key).toBe(true);
|
|
136
|
+
expect(entities.get(key)!.props.mode, key).toBe("live");
|
|
137
|
+
expect(entities.get(key)!.props.estate, key).toBe(ESTATE);
|
|
138
|
+
}
|
|
139
|
+
expect([...entities.keys()].some((k) => k.includes("["))).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("indexes the live-plan document by module-keyed instance address", () => {
|
|
143
|
+
const index = indexLivePlan(LIVE_PLAN);
|
|
144
|
+
expect(index.estate).toBe(ESTATE);
|
|
145
|
+
expect([...index.bound.keys()].sort()).toEqual(["module.app[0].aws_cloudwatch_log_group.logs", ...POOL]);
|
|
146
|
+
expect(index.omissions.get("module.app[1].aws_cloudwatch_log_group.logs")!.reason).toBe("ABSENT");
|
|
147
|
+
expect(index.unowned.get(EAST)).toMatchObject({ adoptEstate: ESTATE, adoptAddress: "module.edge:east.aws_cloudwatch_log_group.front" });
|
|
148
|
+
expect(index.unowned.get(WEST)).toMatchObject({ heldBy: "other-estate" });
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("indexes the state document's keyed child modules and their rows", () => {
|
|
152
|
+
const index = indexStateResources(STATE);
|
|
153
|
+
expect([...index.modules].sort()).toEqual(["module.app[0]", "module.app[1]", 'module.edge["east"]', 'module.edge["west"]']);
|
|
154
|
+
expect(index.rows.get("module.app[1].aws_eip.pool[0]")).toMatchObject({ type: "aws_eip", id: "eipalloc-0c63e9f40bd5172a3" });
|
|
155
|
+
// The module prefix is already on each row, so none gets a second one.
|
|
156
|
+
expect([...index.rows.keys()].filter((k) => k.startsWith("module.app[0].module.app"))).toEqual([]);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
describe("describeResources over a module-keyed live-plan document (#4513)", () => {
|
|
161
|
+
it("rolls a block expanded under an expanded call up to owned, with key and scope per instance", async () => {
|
|
162
|
+
const { entities } = await render("choudoufu");
|
|
163
|
+
const { resources, queried } = normalizeObservation(await describeResources(options(entities), liveDeps()));
|
|
164
|
+
const pool = resources["estate/module.app/aws_eip.pool"]!;
|
|
165
|
+
expect(queried["estate/module.app/aws_eip.pool"]).toBe(
|
|
166
|
+
`choudoufu live-plan -json (root "estate", estate "${ESTATE}", address "module.app.aws_eip.pool")`,
|
|
167
|
+
);
|
|
168
|
+
expect(pool).toMatchObject({
|
|
169
|
+
type: "Terraform::Resource",
|
|
170
|
+
status: "bound",
|
|
171
|
+
ownership: "owned",
|
|
172
|
+
physicalId: "module.app.aws_eip.pool",
|
|
173
|
+
marker: { stack: ESTATE },
|
|
174
|
+
});
|
|
175
|
+
expect(pool.attributes).toMatchObject({ address: "module.app.aws_eip.pool", root: "estate", estate: ESTATE, boundBy: "marker", resourceType: "aws_eip" });
|
|
176
|
+
expect(pool.attributes!.instances).toEqual(POOL);
|
|
177
|
+
expect(pool.instances).toEqual([
|
|
178
|
+
{ key: "[0]", scope: "module.app[0]", address: POOL[0], verdict: "present", ownership: "owned", status: "bound", physicalId: "eipalloc-0a41c7d2e9b3f5061" },
|
|
179
|
+
{ key: "[1]", scope: "module.app[0]", address: POOL[1], verdict: "present", ownership: "owned", status: "bound", physicalId: "eipalloc-0b52d8e3fac4061f2" },
|
|
180
|
+
{ key: "[0]", scope: "module.app[1]", address: POOL[2], verdict: "present", ownership: "owned", status: "bound", physicalId: "eipalloc-0c63e9f40bd5172a3" },
|
|
181
|
+
{ key: "[1]", scope: "module.app[1]", address: POOL[3], verdict: "present", ownership: "owned", status: "bound", physicalId: "eipalloc-0d74fa051ce6283b4" },
|
|
182
|
+
]);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("gives a block only the call expands a scope and no key, and keeps an absent instance", async () => {
|
|
186
|
+
const { entities } = await render("choudoufu");
|
|
187
|
+
const { resources } = normalizeObservation(await describeResources(options(entities), liveDeps()));
|
|
188
|
+
const logs = resources["estate/module.app/aws_cloudwatch_log_group.logs"]!;
|
|
189
|
+
// One instance bound by derivation, the other ABSENT: owned, with the one
|
|
190
|
+
// bound identity, and no marker, because a derived bind read no tag.
|
|
191
|
+
expect(logs).toMatchObject({ status: "bound", ownership: "owned", physicalId: `/${ESTATE}/app-0` });
|
|
192
|
+
expect(logs.marker).toBeUndefined();
|
|
193
|
+
expect(logs.attributes).toMatchObject({ boundBy: "derived" });
|
|
194
|
+
expect(logs.instances).toEqual([
|
|
195
|
+
{
|
|
196
|
+
scope: "module.app[0]",
|
|
197
|
+
address: "module.app[0].aws_cloudwatch_log_group.logs",
|
|
198
|
+
verdict: "present",
|
|
199
|
+
ownership: "owned",
|
|
200
|
+
status: "bound",
|
|
201
|
+
physicalId: `/${ESTATE}/app-0`,
|
|
202
|
+
},
|
|
203
|
+
{ scope: "module.app[1]", address: "module.app[1].aws_cloudwatch_log_group.logs", verdict: "absent" },
|
|
204
|
+
]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("reads a for_each call's string keys, foreign over adoptable", async () => {
|
|
208
|
+
const { entities } = await render("choudoufu");
|
|
209
|
+
const { resources } = normalizeObservation(await describeResources(options(entities), liveDeps()));
|
|
210
|
+
const front = resources["estate/module.edge/aws_cloudwatch_log_group.front"]!;
|
|
211
|
+
expect(front).toMatchObject({ status: "unowned", ownership: "foreign", physicalId: `/${ESTATE}/edge-west` });
|
|
212
|
+
expect(front.attributes).toMatchObject({ heldBy: "other-estate", instances: [EAST, WEST] });
|
|
213
|
+
expect(front.instances).toEqual([
|
|
214
|
+
{ scope: 'module.edge["east"]', address: EAST, verdict: "present", ownership: "unknown", status: "adoptable", physicalId: `/${ESTATE}/edge-east` },
|
|
215
|
+
{ scope: 'module.edge["west"]', address: WEST, verdict: "present", ownership: "foreign", status: "unowned", physicalId: `/${ESTATE}/edge-west` },
|
|
216
|
+
]);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("finds a keyed module call's members by its unkeyed address", async () => {
|
|
220
|
+
const { entities } = await render("choudoufu");
|
|
221
|
+
const { resources } = normalizeObservation(await describeResources(options(entities), liveDeps()));
|
|
222
|
+
expect(resources["estate/module.app"]).toMatchObject({ type: "Terraform::Module", status: "module", ownership: "unknown" });
|
|
223
|
+
expect(resources["estate/module.app"]!.attributes!.instances).toEqual([
|
|
224
|
+
"module.app[0].aws_cloudwatch_log_group.logs",
|
|
225
|
+
...POOL.slice(0, 2),
|
|
226
|
+
"module.app[1].aws_cloudwatch_log_group.logs",
|
|
227
|
+
...POOL.slice(2),
|
|
228
|
+
]);
|
|
229
|
+
expect(resources["estate/module.edge"]!.attributes!.instances).toEqual([EAST, WEST]);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("puts every live instance on a node the declared graph lists", async () => {
|
|
233
|
+
const { declarables, entities } = await render("choudoufu");
|
|
234
|
+
const { resources } = normalizeObservation(await describeResources(options(entities), liveDeps()));
|
|
235
|
+
const live = buildLiveGraphIr([{ lexicon: "terraform", resources }]);
|
|
236
|
+
const declared = withInstanceNodes(buildGraphIr(declarables), declarables);
|
|
237
|
+
const declaredIds = new Set(declared.nodes.map((n) => n.id));
|
|
238
|
+
|
|
239
|
+
const liveInstances = live.nodes.filter((n) => n.instanceOf).map((n) => n.id).sort();
|
|
240
|
+
expect(liveInstances).toEqual([
|
|
241
|
+
"estate/module.app[0]/aws_cloudwatch_log_group.logs",
|
|
242
|
+
"estate/module.app[0]/aws_eip.pool[0]",
|
|
243
|
+
"estate/module.app[0]/aws_eip.pool[1]",
|
|
244
|
+
"estate/module.app[1]/aws_eip.pool[0]",
|
|
245
|
+
"estate/module.app[1]/aws_eip.pool[1]",
|
|
246
|
+
'estate/module.edge["east"]/aws_cloudwatch_log_group.front',
|
|
247
|
+
'estate/module.edge["west"]/aws_cloudwatch_log_group.front',
|
|
248
|
+
]);
|
|
249
|
+
for (const id of liveInstances) expect(declaredIds.has(id), id).toBe(true);
|
|
250
|
+
|
|
251
|
+
// The absent instance draws no live node, so the overlay leaves the
|
|
252
|
+
// declared one unmatched while its bound sibling matches.
|
|
253
|
+
const status = new Map(overlayGraphs(live, declared).nodes.map((n) => [n.id, n.attrs._status]));
|
|
254
|
+
expect(status.get("estate/module.app[0]/aws_cloudwatch_log_group.logs")).toBe("good");
|
|
255
|
+
expect(status.get("estate/module.app[1]/aws_cloudwatch_log_group.logs")).toBe("accent");
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe("describeResources over a module-keyed state document (#4513)", () => {
|
|
260
|
+
it("reads each block's rows under keyed child modules as its instances", async () => {
|
|
261
|
+
const { entities } = await render("tofu");
|
|
262
|
+
const { resources, queried } = normalizeObservation(await describeResources(options(entities), stateDeps()));
|
|
263
|
+
expect(queried["estate/module.app/aws_eip.pool"]).toBe('terraform show -json (root "estate", address "module.app.aws_eip.pool")');
|
|
264
|
+
const pool = resources["estate/module.app/aws_eip.pool"]!;
|
|
265
|
+
expect(pool).toMatchObject({ status: "managed", ownership: "owned", physicalId: "module.app.aws_eip.pool" });
|
|
266
|
+
expect(pool.attributes!.instances).toEqual(POOL);
|
|
267
|
+
expect(pool.instances!.map((i) => [i.key, i.scope, i.physicalId])).toEqual([
|
|
268
|
+
["[0]", "module.app[0]", "eipalloc-0a41c7d2e9b3f5061"],
|
|
269
|
+
["[1]", "module.app[0]", "eipalloc-0b52d8e3fac4061f2"],
|
|
270
|
+
["[0]", "module.app[1]", "eipalloc-0c63e9f40bd5172a3"],
|
|
271
|
+
["[1]", "module.app[1]", "eipalloc-0d74fa051ce6283b4"],
|
|
272
|
+
]);
|
|
273
|
+
|
|
274
|
+
const front = resources["estate/module.edge/aws_cloudwatch_log_group.front"]!;
|
|
275
|
+
expect(front.instances!.map((i) => [i.key, i.scope])).toEqual([
|
|
276
|
+
[undefined, 'module.edge["east"]'],
|
|
277
|
+
[undefined, 'module.edge["west"]'],
|
|
278
|
+
]);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("reports a keyed module call present from its child_modules entries", async () => {
|
|
282
|
+
// A keyed call's child_modules[] entries are `module.app[0]`, never
|
|
283
|
+
// `module.app`, and neither its rows nor they start with `module.app.`,
|
|
284
|
+
// so a prefix test on the unkeyed address read the call as absent.
|
|
285
|
+
const { entities } = await render("tofu");
|
|
286
|
+
const { resources } = normalizeObservation(await describeResources(options(entities), stateDeps()));
|
|
287
|
+
expect(resources["estate/module.app"]).toMatchObject({ type: "Terraform::Module", status: "module", physicalId: "module.app" });
|
|
288
|
+
expect(resources["estate/module.edge"]).toMatchObject({ type: "Terraform::Module", status: "module", physicalId: "module.edge" });
|
|
289
|
+
});
|
|
290
|
+
});
|