@intentius/chant-lexicon-terraform 0.124.52 → 0.124.55
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 +14 -10
- 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/ci-setup.d.ts +11 -0
- package/dist/ci-setup.d.ts.map +1 -0
- package/dist/ci-setup.js +41 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +4 -3
- package/dist/components/capability-plugin.d.ts +105 -9
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability-plugin.js +357 -36
- 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/components/release-inputs.d.ts +29 -0
- package/dist/components/release-inputs.d.ts.map +1 -0
- package/dist/components/release-inputs.js +57 -0
- package/dist/components/trace-facts.d.ts +16 -0
- package/dist/components/trace-facts.d.ts.map +1 -0
- package/dist/components/trace-facts.js +19 -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/cone.d.ts +53 -0
- package/dist/cone.d.ts.map +1 -0
- package/dist/cone.js +119 -0
- package/dist/config.d.ts +59 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -9
- package/dist/cost-hold.d.ts +27 -0
- package/dist/cost-hold.d.ts.map +1 -0
- package/dist/cost-hold.js +21 -0
- 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/drift-rows.d.ts +61 -0
- package/dist/drift-rows.d.ts.map +1 -0
- package/dist/drift-rows.js +108 -0
- package/dist/exit-codes.d.ts +55 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +48 -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 +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -2
- package/dist/integrity.json +8 -5
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-catalog.js +27 -3
- package/dist/lint/audit-lineage.d.ts +14 -2
- package/dist/lint/audit-lineage.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/index.js +4 -0
- package/dist/lint/post-synth/record-store.d.ts +54 -0
- package/dist/lint/post-synth/record-store.d.ts.map +1 -0
- package/dist/lint/post-synth/record-store.js +104 -0
- package/dist/lint/post-synth/tf001.d.ts +2 -2
- package/dist/lint/post-synth/tf001.js +2 -2
- package/dist/lint/post-synth/tf024.d.ts +35 -11
- package/dist/lint/post-synth/tf024.d.ts.map +1 -1
- package/dist/lint/post-synth/tf024.js +92 -20
- package/dist/lint/post-synth/tf046.d.ts +64 -0
- package/dist/lint/post-synth/tf046.d.ts.map +1 -0
- package/dist/lint/post-synth/tf046.js +175 -0
- package/dist/lint/post-synth/tf047.d.ts +36 -0
- package/dist/lint/post-synth/tf047.d.ts.map +1 -0
- package/dist/lint/post-synth/tf047.js +94 -0
- 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/lock-rows.d.ts +36 -0
- package/dist/lock-rows.d.ts.map +1 -0
- package/dist/lock-rows.js +60 -0
- package/dist/lock-timeout.d.ts +22 -0
- package/dist/lock-timeout.d.ts.map +1 -0
- package/dist/lock-timeout.js +32 -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/module-catalog/index.d.ts +69 -0
- package/dist/module-catalog/index.d.ts.map +1 -0
- package/dist/module-catalog/index.js +110 -0
- package/dist/module-catalog/refresh-cli.d.ts +4 -0
- package/dist/module-catalog/refresh-cli.d.ts.map +1 -0
- package/dist/module-catalog/refresh-cli.js +64 -0
- package/dist/module-catalog/static-tier.d.ts +6 -0
- package/dist/module-catalog/static-tier.d.ts.map +1 -0
- package/dist/module-catalog/static-tier.js +1650 -0
- package/dist/module-catalog/types.d.ts +65 -0
- package/dist/module-catalog/types.d.ts.map +1 -0
- package/dist/module-catalog/types.js +33 -0
- package/dist/okf/index.md +3 -1
- package/dist/okf/rules/TF024.md +2 -2
- package/dist/okf/rules/TF046.md +11 -0
- package/dist/okf/rules/TF047.md +11 -0
- 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 +182 -5
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/activities/terraform.js +224 -24
- 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/consumers.d.ts +35 -0
- package/dist/pin/consumers.d.ts.map +1 -0
- package/dist/pin/consumers.js +70 -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 +37 -18
- package/dist/registry/address.d.ts +63 -0
- package/dist/registry/address.d.ts.map +1 -0
- package/dist/registry/address.js +65 -0
- package/dist/registry/catalog-read.d.ts +14 -0
- package/dist/registry/catalog-read.d.ts.map +1 -0
- package/dist/registry/catalog-read.js +58 -0
- package/dist/registry/deprecated.d.ts +37 -0
- package/dist/registry/deprecated.d.ts.map +1 -0
- package/dist/registry/deprecated.js +43 -0
- package/dist/registry/docs.d.ts +96 -0
- package/dist/registry/docs.d.ts.map +1 -0
- package/dist/registry/docs.js +210 -0
- package/dist/registry/edge/edge.d.ts +46 -0
- package/dist/registry/edge/edge.d.ts.map +1 -0
- package/dist/registry/edge/edge.js +194 -0
- package/dist/registry/edge/index.d.ts +11 -0
- package/dist/registry/edge/index.d.ts.map +1 -0
- package/dist/registry/edge/index.js +10 -0
- package/dist/registry/edge/lambda-edge.d.ts +76 -0
- package/dist/registry/edge/lambda-edge.d.ts.map +1 -0
- package/dist/registry/edge/lambda-edge.js +95 -0
- package/dist/registry/edge/sigv4-web.d.ts +33 -0
- package/dist/registry/edge/sigv4-web.d.ts.map +1 -0
- package/dist/registry/edge/sigv4-web.js +56 -0
- package/dist/registry/edge/token-source.d.ts +73 -0
- package/dist/registry/edge/token-source.d.ts.map +1 -0
- package/dist/registry/edge/token-source.js +115 -0
- package/dist/registry/edge/worker.d.ts +45 -0
- package/dist/registry/edge/worker.d.ts.map +1 -0
- package/dist/registry/edge/worker.js +26 -0
- package/dist/registry/handler.d.ts +25 -0
- package/dist/registry/handler.d.ts.map +1 -0
- package/dist/registry/handler.js +75 -0
- package/dist/registry/headers-file.d.ts +21 -0
- package/dist/registry/headers-file.d.ts.map +1 -0
- package/dist/registry/headers-file.js +57 -0
- package/dist/registry/index.d.ts +31 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +30 -0
- package/dist/registry/mirror-paths.d.ts +9 -0
- package/dist/registry/mirror-paths.d.ts.map +1 -0
- package/dist/registry/mirror-paths.js +8 -0
- package/dist/registry/mirror.d.ts +130 -0
- package/dist/registry/mirror.d.ts.map +1 -0
- package/dist/registry/mirror.js +319 -0
- package/dist/registry/proxies.d.ts +73 -0
- package/dist/registry/proxies.d.ts.map +1 -0
- package/dist/registry/proxies.js +111 -0
- package/dist/registry/reader.d.ts +57 -0
- package/dist/registry/reader.d.ts.map +1 -0
- package/dist/registry/reader.js +198 -0
- package/dist/registry/semver.d.ts +16 -0
- package/dist/registry/semver.d.ts.map +1 -0
- package/dist/registry/semver.js +24 -0
- package/dist/registry/serve.d.ts +24 -0
- package/dist/registry/serve.d.ts.map +1 -0
- package/dist/registry/serve.js +64 -0
- package/dist/registry/source-forms.d.ts +79 -0
- package/dist/registry/source-forms.d.ts.map +1 -0
- package/dist/registry/source-forms.js +202 -0
- package/dist/registry/targets/artifactory.d.ts +28 -0
- package/dist/registry/targets/artifactory.d.ts.map +1 -0
- package/dist/registry/targets/artifactory.js +206 -0
- package/dist/registry/targets/fake-artifactory.d.ts +30 -0
- package/dist/registry/targets/fake-artifactory.d.ts.map +1 -0
- package/dist/registry/targets/fake-artifactory.js +142 -0
- package/dist/registry/targets/fake-gitlab.d.ts +39 -0
- package/dist/registry/targets/fake-gitlab.d.ts.map +1 -0
- package/dist/registry/targets/fake-gitlab.js +136 -0
- package/dist/registry/targets/fake-hcp.d.ts +50 -0
- package/dist/registry/targets/fake-hcp.d.ts.map +1 -0
- package/dist/registry/targets/fake-hcp.js +202 -0
- package/dist/registry/targets/fake-http.d.ts +31 -0
- package/dist/registry/targets/fake-http.d.ts.map +1 -0
- package/dist/registry/targets/fake-http.js +87 -0
- package/dist/registry/targets/fake-nexus.d.ts +27 -0
- package/dist/registry/targets/fake-nexus.d.ts.map +1 -0
- package/dist/registry/targets/fake-nexus.js +137 -0
- package/dist/registry/targets/gitlab.d.ts +53 -0
- package/dist/registry/targets/gitlab.d.ts.map +1 -0
- package/dist/registry/targets/gitlab.js +187 -0
- package/dist/registry/targets/hcp.d.ts +29 -0
- package/dist/registry/targets/hcp.d.ts.map +1 -0
- package/dist/registry/targets/hcp.js +310 -0
- package/dist/registry/targets/hosted.d.ts +62 -0
- package/dist/registry/targets/hosted.d.ts.map +1 -0
- package/dist/registry/targets/hosted.js +74 -0
- package/dist/registry/targets/index.d.ts +18 -0
- package/dist/registry/targets/index.d.ts.map +1 -0
- package/dist/registry/targets/index.js +17 -0
- package/dist/registry/targets/module-target.d.ts +68 -0
- package/dist/registry/targets/module-target.d.ts.map +1 -0
- package/dist/registry/targets/module-target.js +63 -0
- package/dist/registry/targets/nexus.d.ts +43 -0
- package/dist/registry/targets/nexus.d.ts.map +1 -0
- package/dist/registry/targets/nexus.js +250 -0
- package/dist/registry/targets/zip.d.ts +55 -0
- package/dist/registry/targets/zip.d.ts.map +1 -0
- package/dist/registry/targets/zip.js +278 -0
- package/dist/registry/writer.d.ts +101 -0
- package/dist/registry/writer.d.ts.map +1 -0
- package/dist/registry/writer.js +109 -0
- package/dist/report.d.ts +15 -6
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +28 -55
- package/dist/rules/record-store.ts +122 -0
- package/dist/rules/tf001.ts +2 -2
- package/dist/rules/tf024.ts +105 -22
- package/dist/rules/tf046.ts +204 -0
- package/dist/rules/tf047.ts +114 -0
- package/dist/skills/chant-terraform.md +1 -1
- package/dist/state/azure-blob.d.ts +9 -0
- package/dist/state/azure-blob.d.ts.map +1 -0
- package/dist/state/azure-blob.js +8 -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 +8 -0
- package/dist/state/gcs.d.ts.map +1 -0
- package/dist/state/gcs.js +7 -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 +8 -0
- package/dist/state/object-store.d.ts.map +1 -0
- package/dist/state/object-store.js +7 -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 +21 -0
- package/dist/state/s3.d.ts.map +1 -0
- package/dist/state/s3.js +19 -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/state-ops.d.ts +255 -0
- package/dist/state-ops.d.ts.map +1 -0
- package/dist/state-ops.js +305 -0
- package/dist/state-reads.d.ts +57 -0
- package/dist/state-reads.d.ts.map +1 -0
- package/dist/state-reads.js +104 -0
- package/dist/terragrunt/affected.d.ts.map +1 -1
- package/dist/terragrunt/affected.js +2 -1
- package/dist/used-sources.d.ts +54 -0
- package/dist/used-sources.d.ts.map +1 -0
- package/dist/used-sources.js +157 -0
- package/package.json +24 -4
- 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 +16 -0
- package/src/__fixtures__/drift-record/live-plan-sections.json +27 -0
- package/src/__fixtures__/drift-rows/live-root-plan.json +70 -0
- package/src/__fixtures__/drift-rows/refresh-plan.json +61 -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/__fixtures__/used-sources/root/extra.tofu +1 -0
- package/src/__fixtures__/used-sources/root/main.tf +31 -0
- package/src/__fixtures__/used-sources/root/modules/net/main.tf +14 -0
- package/src/__fixtures__/used-sources/root/modules/net/versions.tf.json +7 -0
- package/src/__fixtures__/used-sources/unit/terragrunt.hcl +3 -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/ci-setup.ts +42 -0
- package/src/commands.ts +4 -3
- package/src/components/capability-plugin.test.ts +198 -19
- package/src/components/capability-plugin.ts +383 -35
- 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 +113 -57
- package/src/components/release-inputs.ts +69 -0
- package/src/components/trace-facts.test.ts +21 -0
- package/src/components/trace-facts.ts +27 -0
- 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/cone.ts +138 -0
- package/src/config-file-listers.test.ts +265 -0
- package/src/config.ts +44 -9
- package/src/cost-hold.ts +29 -0
- package/src/describe-resources.engine-facts.test.ts +411 -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/drift-rows.test.ts +135 -0
- package/src/drift-rows.ts +137 -0
- package/src/exit-codes.test.ts +23 -0
- package/src/exit-codes.ts +59 -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 +79 -0
- package/src/lint/audit-catalog.ts +29 -3
- package/src/lint/audit-lineage.ts +14 -2
- package/src/lint/post-synth/fixtures/TF024/live-with-record-store/main.tf +18 -0
- package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/estate.chdf.hcl +1 -0
- package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/main.tf +10 -0
- package/src/lint/post-synth/fixtures/TF046/azurerm-no-resource-group/main.tf +15 -0
- package/src/lint/post-synth/fixtures/TF046/backend-config-only/main.tf +14 -0
- package/src/lint/post-synth/fixtures/TF046/derived-s3/backend.tf +7 -0
- package/src/lint/post-synth/fixtures/TF046/derived-s3/main.tf +9 -0
- package/src/lint/post-synth/fixtures/TF046/explicit-local/main.tf +16 -0
- package/src/lint/post-synth/fixtures/TF046/explicit-s3-beside-local-backend/main.tf +15 -0
- package/src/lint/post-synth/fixtures/TF046/implied-local/main.tf +9 -0
- package/src/lint/post-synth/fixtures/TF046/sidecar-implied/estate.chdf.hcl +1 -0
- package/src/lint/post-synth/fixtures/TF046/sidecar-implied/main.tf +5 -0
- package/src/lint/post-synth/fixtures/TF047/clear/main.tf +12 -0
- package/src/lint/post-synth/fixtures/TF047/refused/main.tf +12 -0
- package/src/lint/post-synth/fixtures/TF047/unknown-module/main.tf +12 -0
- package/src/lint/post-synth/fixtures/TF047/unknown-version/main.tf +12 -0
- package/src/lint/post-synth/index.ts +4 -0
- package/src/lint/post-synth/record-store.ts +122 -0
- package/src/lint/post-synth/tf001.ts +2 -2
- package/src/lint/post-synth/tf024.test.ts +26 -5
- package/src/lint/post-synth/tf024.ts +105 -22
- package/src/lint/post-synth/tf046.test.ts +137 -0
- package/src/lint/post-synth/tf046.ts +204 -0
- package/src/lint/post-synth/tf047.test.ts +56 -0
- package/src/lint/post-synth/tf047.ts +114 -0
- package/src/live-plan-reasons.ts +54 -0
- package/src/lock-rows.test.ts +70 -0
- package/src/lock-rows.ts +82 -0
- package/src/lock-timeout.ts +34 -0
- package/src/lsp/completions.test.ts +1 -1
- package/src/lsp/option-keys.ts +2 -0
- package/src/module-catalog/index.test.ts +93 -0
- package/src/module-catalog/index.ts +159 -0
- package/src/module-catalog/refresh-cli.ts +68 -0
- package/src/module-catalog/static-tier.ts +1659 -0
- package/src/module-catalog/types.ts +88 -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 +312 -27
- 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/op-wave-step.test.ts +109 -0
- package/src/pin/__fixtures__/consumers/live/dev/main.tf +4 -0
- package/src/pin/__fixtures__/consumers/live/prod/main.tf +21 -0
- package/src/pin/__fixtures__/consumers/units/vpc/terragrunt.hcl +7 -0
- package/src/pin/bundle.test.ts +2 -0
- package/src/pin/consumers.test.ts +57 -0
- package/src/pin/consumers.ts +95 -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 +39 -19
- package/src/registry/__fixtures__/docs/documented/.terraform-docs.yml +3 -0
- package/src/registry/__fixtures__/docs/documented/README.md +1 -0
- package/src/registry/__fixtures__/docs/documented/main.tf +8 -0
- package/src/registry/__fixtures__/docs/json/main.tf.json +14 -0
- package/src/registry/__fixtures__/docs/vpc/README.md +3 -0
- package/src/registry/__fixtures__/docs/vpc/examples/complete/main.tf +5 -0
- package/src/registry/__fixtures__/docs/vpc/examples/simple/README.md +1 -0
- package/src/registry/__fixtures__/docs/vpc/examples/simple/main.tf +4 -0
- package/src/registry/__fixtures__/docs/vpc/main.tf +14 -0
- package/src/registry/__fixtures__/docs/vpc/outputs.tf +9 -0
- package/src/registry/__fixtures__/docs/vpc/variables.tf +16 -0
- package/src/registry/__fixtures__/proxied-root/main.tf +12 -0
- package/src/registry/address.ts +100 -0
- package/src/registry/catalog-read.ts +56 -0
- package/src/registry/deprecated.test.ts +139 -0
- package/src/registry/deprecated.ts +76 -0
- package/src/registry/docs.test.ts +140 -0
- package/src/registry/docs.ts +299 -0
- package/src/registry/edge/bundle.test.ts +50 -0
- package/src/registry/edge/edge.test.ts +176 -0
- package/src/registry/edge/edge.ts +211 -0
- package/src/registry/edge/index.ts +10 -0
- package/src/registry/edge/lambda-edge.ts +127 -0
- package/src/registry/edge/sigv4-web.ts +79 -0
- package/src/registry/edge/token-source.test.ts +258 -0
- package/src/registry/edge/token-source.ts +169 -0
- package/src/registry/edge/worker.ts +61 -0
- package/src/registry/handler.ts +89 -0
- package/src/registry/headers-file.ts +61 -0
- package/src/registry/index.ts +31 -0
- package/src/registry/mirror-paths.ts +10 -0
- package/src/registry/mirror.test.ts +198 -0
- package/src/registry/mirror.ts +395 -0
- package/src/registry/proxies.test.ts +153 -0
- package/src/registry/proxies.ts +132 -0
- package/src/registry/reader.ts +225 -0
- package/src/registry/registry.test.ts +262 -0
- package/src/registry/semver.ts +34 -0
- package/src/registry/serve.ts +82 -0
- package/src/registry/source-forms.test.ts +87 -0
- package/src/registry/source-forms.ts +216 -0
- package/src/registry/targets/artifactory.test.ts +248 -0
- package/src/registry/targets/artifactory.ts +257 -0
- package/src/registry/targets/fake-artifactory.ts +158 -0
- package/src/registry/targets/fake-gitlab.ts +161 -0
- package/src/registry/targets/fake-hcp.ts +233 -0
- package/src/registry/targets/fake-http.ts +97 -0
- package/src/registry/targets/fake-nexus.ts +152 -0
- package/src/registry/targets/gitlab.test.ts +208 -0
- package/src/registry/targets/gitlab.ts +223 -0
- package/src/registry/targets/hcp.test.ts +230 -0
- package/src/registry/targets/hcp.ts +360 -0
- package/src/registry/targets/hosted.ts +117 -0
- package/src/registry/targets/index.ts +17 -0
- package/src/registry/targets/module-target.ts +131 -0
- package/src/registry/targets/nexus.test.ts +220 -0
- package/src/registry/targets/nexus.ts +314 -0
- package/src/registry/targets/zip.test.ts +65 -0
- package/src/registry/targets/zip.ts +287 -0
- package/src/registry/writer.ts +155 -0
- package/src/report.test.ts +82 -1
- package/src/report.ts +31 -54
- package/src/signal-only-root.test.ts +72 -0
- package/src/skills/chant-terraform.md +1 -1
- package/src/state/azure-blob.ts +8 -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 +7 -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 +7 -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 +21 -0
- package/src/state/store.ts +225 -0
- package/src/state-ops.test.ts +182 -0
- package/src/state-ops.ts +462 -0
- package/src/state-reads.ts +116 -0
- package/src/terragrunt/affected.ts +2 -1
- package/src/used-sources.test.ts +75 -0
- package/src/used-sources.ts +204 -0
- 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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composed plan cut back into one plan per member (chant#4442, epic
|
|
3
|
+
* #4419): each member's part of the composed root's `show -json`, as if the
|
|
4
|
+
* member's root had planned alone, and from it the member's change-set part,
|
|
5
|
+
* planned outputs, plan shape and reads of other members, so the change set,
|
|
6
|
+
* the report, policy and behold see each component and not one composed
|
|
7
|
+
* root.
|
|
8
|
+
*
|
|
9
|
+
* Lifted from terragucci's `packages/terragucci/src/compose.ts` at c493e0e
|
|
10
|
+
* (`slicePlan`, `sliceText`, `planCounts`, `composedReportReads`). Addresses
|
|
11
|
+
* are stripped by `./module-address`, which `chant terraform report` uses
|
|
12
|
+
* too. The outputs are `<m>__<name>` in the composed root, as #4441 writes
|
|
13
|
+
* them and terragucci did.
|
|
14
|
+
*/
|
|
15
|
+
import type { ChangeSetPlanner, ChangeSetPart } from "@intentius/chant/change-set";
|
|
16
|
+
import type { CapabilityPlan, PlannedOutputs } from "@intentius/chant/components/capability";
|
|
17
|
+
import type { PlanShape } from "@intentius/chant/components/covered-round";
|
|
18
|
+
import type { Composition, ComposedRead } from "../compose.js";
|
|
19
|
+
type Json = Record<string, unknown>;
|
|
20
|
+
/** The outputs of module `m` among a composed root's, by their own names. */
|
|
21
|
+
export declare function moduleOutputs(outputs: unknown, m: string): Json;
|
|
22
|
+
/** A module's part of `planned_values` or `prior_state.values`: its child module as the root module, addresses unprefixed. */
|
|
23
|
+
export declare function moduleValues(values: unknown, m: string, outputs: Json): Json | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* One member's part of the composed plan's `show -json`, as if it had
|
|
26
|
+
* planned alone: its resource changes and drift with `module.<m>.` taken off,
|
|
27
|
+
* its outputs by their own names, its planned values, prior state and
|
|
28
|
+
* configuration as the root module. `checks` and `variables` (the composed
|
|
29
|
+
* root's) are left out.
|
|
30
|
+
*/
|
|
31
|
+
export declare function slicePlan(plan: unknown, m: string): unknown;
|
|
32
|
+
/** A plan's counts as the binary's `Plan:` line gives them, and how many changes and destroys it holds. */
|
|
33
|
+
export interface PlanCounts {
|
|
34
|
+
add: number;
|
|
35
|
+
change: number;
|
|
36
|
+
destroy: number;
|
|
37
|
+
changes: number;
|
|
38
|
+
destroys: number;
|
|
39
|
+
}
|
|
40
|
+
/** A plan's counts as the binary's `Plan:` line gives them. A no-op or read is not a change. */
|
|
41
|
+
export declare function planCounts(plan: unknown): PlanCounts;
|
|
42
|
+
/**
|
|
43
|
+
* One member's part of the composed plan's `show` text: the text before the
|
|
44
|
+
* actions, each resource block of its module with `module.<m>.` taken off,
|
|
45
|
+
* its line of counts, and its outputs by their own names.
|
|
46
|
+
*/
|
|
47
|
+
export declare function sliceText(text: string, m: string, counts: {
|
|
48
|
+
add: number;
|
|
49
|
+
change: number;
|
|
50
|
+
destroy: number;
|
|
51
|
+
}): string;
|
|
52
|
+
/** One member's read of another member's outputs, planned on the upstream's part of the composed plan. */
|
|
53
|
+
export interface ComposedMemberRead {
|
|
54
|
+
/** The member read. */
|
|
55
|
+
upstream: string;
|
|
56
|
+
via: ComposedRead["via"];
|
|
57
|
+
/** The `vars` key, or the data block's label. */
|
|
58
|
+
name: string;
|
|
59
|
+
/** The outputs read, sorted. Undefined when the reader reads the whole object, so every output counts. */
|
|
60
|
+
outputs?: string[];
|
|
61
|
+
/** The outputs read that are known only once the upstream's part applies, sorted. */
|
|
62
|
+
unknown: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Each member's reads of other members, planned on the upstream's part of
|
|
66
|
+
* the composed plan: an output read that the upstream's planned outputs
|
|
67
|
+
* ({@link terraformPlannedOutputs} of its slice) leave unknown is named
|
|
68
|
+
* unknown. A `vars` read names its output; a `terraform_remote_state` or
|
|
69
|
+
* `terraform_estate_outputs` block's outputs are read from the member's own
|
|
70
|
+
* files, as terragucci's `outputsRead` and `estateValuesRead` did.
|
|
71
|
+
*/
|
|
72
|
+
export declare function composedReads(c: Pick<Composition, "members" | "reads" | "dirs"> & Partial<Pick<Composition, "binary">>, outputs: ReadonlyMap<string, PlannedOutputs>): Map<string, ComposedMemberRead[]>;
|
|
73
|
+
/** One member's part of a composed plan, in the form a capability's `plan` answers it. */
|
|
74
|
+
export interface ComposedMemberPlan extends CapabilityPlan {
|
|
75
|
+
/** The member's root, as `terraform.roots` names it: the change set's member. */
|
|
76
|
+
member: string;
|
|
77
|
+
changeSet: ChangeSetPart;
|
|
78
|
+
outputs: PlannedOutputs;
|
|
79
|
+
/** `unknownInputs` are this member's reads of other members that the composed plan leaves unknown, as `<component>.<output>`. */
|
|
80
|
+
shape: PlanShape;
|
|
81
|
+
/** The member's part of `show -json`, as if it had planned alone. */
|
|
82
|
+
slice: unknown;
|
|
83
|
+
counts: PlanCounts;
|
|
84
|
+
/** Its reads of other members. */
|
|
85
|
+
reads: ComposedMemberRead[];
|
|
86
|
+
}
|
|
87
|
+
export interface ComposedMemberPlansOptions {
|
|
88
|
+
/** The binary that planned. Default `terraform`. */
|
|
89
|
+
planner?: ChangeSetPlanner;
|
|
90
|
+
/** The estate or workspace each member plans into, by component. */
|
|
91
|
+
scope?: (member: string) => string | undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Every member's plan out of the composed plan's `show -json`, by component:
|
|
95
|
+
* {@link terraformChangeSetPart}, {@link terraformPlannedOutputs} and
|
|
96
|
+
* {@link terraformPlanShape} of its slice, so each member's part is the part
|
|
97
|
+
* a plan of its root alone gives on the same state. The member is the root's
|
|
98
|
+
* name (`Composition.roots`), as a single `terraform-apply` plan names it.
|
|
99
|
+
*/
|
|
100
|
+
export declare function composedMemberPlans(c: Pick<Composition, "members" | "order" | "modules" | "reads" | "dirs" | "roots"> & Partial<Pick<Composition, "binary">>, plan: unknown, options?: ComposedMemberPlansOptions): Record<string, ComposedMemberPlan>;
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=slice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slice.d.ts","sourceRoot":"","sources":["../../src/compose/slice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAC7F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ5D,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAGpC,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAG/D;AAED,8HAA8H;AAC9H,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAWxF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAiC3D;AAED,2GAA2G;AAC3G,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,CAepD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAmCnH;AA0BD,0GAA0G;AAC1G,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACzB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,qFAAqF;IACrF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CA2BxM;AAID,0FAA0F;AAC1F,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,iIAAiI;IACjI,KAAK,EAAE,SAAS,CAAC;IACjB,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,kCAAkC;IAClC,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IACzC,oDAAoD;IACpD,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,oEAAoE;IACpE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAChD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAwB1P"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composed plan cut back into one plan per member (chant#4442, epic
|
|
3
|
+
* #4419): each member's part of the composed root's `show -json`, as if the
|
|
4
|
+
* member's root had planned alone, and from it the member's change-set part,
|
|
5
|
+
* planned outputs, plan shape and reads of other members, so the change set,
|
|
6
|
+
* the report, policy and behold see each component and not one composed
|
|
7
|
+
* root.
|
|
8
|
+
*
|
|
9
|
+
* Lifted from terragucci's `packages/terragucci/src/compose.ts` at c493e0e
|
|
10
|
+
* (`slicePlan`, `sliceText`, `planCounts`, `composedReportReads`). Addresses
|
|
11
|
+
* are stripped by `./module-address`, which `chant terraform report` uses
|
|
12
|
+
* too. The outputs are `<m>__<name>` in the composed root, as #4441 writes
|
|
13
|
+
* them and terragucci did.
|
|
14
|
+
*/
|
|
15
|
+
import { terraformChangeSetPart } from "../change-set.js";
|
|
16
|
+
import { terraformPlannedOutputs } from "../components/capability-plugin.js";
|
|
17
|
+
import { terraformPlanShape } from "../plan-shape.js";
|
|
18
|
+
import { rootTexts } from "./hcl.js";
|
|
19
|
+
import { inModule, moduleChanges, stripModule, topModule } from "./module-address.js";
|
|
20
|
+
import { READ_VAR_PREFIX } from "./root.js";
|
|
21
|
+
const isObj = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
22
|
+
/** The outputs of module `m` among a composed root's, by their own names. */
|
|
23
|
+
export function moduleOutputs(outputs, m) {
|
|
24
|
+
if (!isObj(outputs))
|
|
25
|
+
return {};
|
|
26
|
+
return Object.fromEntries(Object.entries(outputs).filter(([k]) => k.startsWith(`${m}__`)).map(([k, v]) => [k.slice(m.length + 2), v]));
|
|
27
|
+
}
|
|
28
|
+
/** A module's part of `planned_values` or `prior_state.values`: its child module as the root module, addresses unprefixed. */
|
|
29
|
+
export function moduleValues(values, m, outputs) {
|
|
30
|
+
if (!isObj(values))
|
|
31
|
+
return undefined;
|
|
32
|
+
const root = isObj(values.root_module) ? values.root_module : {};
|
|
33
|
+
const child = (Array.isArray(root.child_modules) ? root.child_modules : []).find((x) => isObj(x) && x.address === `module.${m}`);
|
|
34
|
+
const strip = (mod) => ({
|
|
35
|
+
...mod,
|
|
36
|
+
...(Array.isArray(mod.resources) ? { resources: mod.resources.map((x) => (isObj(x) ? { ...x, address: stripModule(String(x.address)) } : x)) } : {}),
|
|
37
|
+
...(Array.isArray(mod.child_modules) ? { child_modules: mod.child_modules.map((x) => (isObj(x) ? strip({ ...x, address: stripModule(String(x.address)) }) : x)) } : {}),
|
|
38
|
+
});
|
|
39
|
+
const { address: _a, ...rest } = child ? strip(child) : { address: undefined };
|
|
40
|
+
return { ...values, outputs, root_module: rest };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* One member's part of the composed plan's `show -json`, as if it had
|
|
44
|
+
* planned alone: its resource changes and drift with `module.<m>.` taken off,
|
|
45
|
+
* its outputs by their own names, its planned values, prior state and
|
|
46
|
+
* configuration as the root module. `checks` and `variables` (the composed
|
|
47
|
+
* root's) are left out.
|
|
48
|
+
*/
|
|
49
|
+
export function slicePlan(plan, m) {
|
|
50
|
+
if (!isObj(plan))
|
|
51
|
+
return plan;
|
|
52
|
+
const out = { ...plan };
|
|
53
|
+
if (Array.isArray(plan.resource_changes))
|
|
54
|
+
out.resource_changes = moduleChanges(plan.resource_changes, m);
|
|
55
|
+
if (Array.isArray(plan.resource_drift))
|
|
56
|
+
out.resource_drift = moduleChanges(plan.resource_drift, m);
|
|
57
|
+
if (isObj(plan.output_changes))
|
|
58
|
+
out.output_changes = moduleOutputs(plan.output_changes, m);
|
|
59
|
+
if (isObj(plan.planned_values))
|
|
60
|
+
out.planned_values = moduleValues(plan.planned_values, m, moduleOutputs(plan.planned_values.outputs, m));
|
|
61
|
+
if (isObj(plan.prior_state)) {
|
|
62
|
+
const values = isObj(plan.prior_state.values) ? plan.prior_state.values : undefined;
|
|
63
|
+
out.prior_state = { ...plan.prior_state, ...(values ? { values: moduleValues(values, m, moduleOutputs(values.outputs, m)) } : {}) };
|
|
64
|
+
}
|
|
65
|
+
if (isObj(plan.configuration)) {
|
|
66
|
+
const root = isObj(plan.configuration.root_module) ? plan.configuration.root_module : {};
|
|
67
|
+
const call = isObj(root.module_calls) && isObj(root.module_calls[m]) ? root.module_calls[m] : undefined;
|
|
68
|
+
const pc = isObj(plan.configuration.provider_config) ? plan.configuration.provider_config : {};
|
|
69
|
+
out.configuration = {
|
|
70
|
+
...plan.configuration,
|
|
71
|
+
provider_config: Object.fromEntries(Object.entries(pc).flatMap(([k, v]) => k.startsWith(`module.${m}:`) ? [[k.slice(`module.${m}:`.length), isObj(v) ? { ...v, module_address: undefined } : v]] : k.includes(":") ? [] : [[k, v]])),
|
|
72
|
+
root_module: isObj(call?.module) ? call.module : {},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(plan.relevant_attributes)) {
|
|
76
|
+
out.relevant_attributes = plan.relevant_attributes
|
|
77
|
+
.filter((x) => isObj(x) && inModule(String(x.resource), m) && String(x.resource) !== `module.${m}`)
|
|
78
|
+
.map((x) => ({ ...x, resource: stripModule(String(x.resource)) }));
|
|
79
|
+
}
|
|
80
|
+
delete out.checks;
|
|
81
|
+
delete out.variables;
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
/** A plan's counts as the binary's `Plan:` line gives them. A no-op or read is not a change. */
|
|
85
|
+
export function planCounts(plan) {
|
|
86
|
+
const rc = isObj(plan) && Array.isArray(plan.resource_changes) ? plan.resource_changes : [];
|
|
87
|
+
let add = 0;
|
|
88
|
+
let change = 0;
|
|
89
|
+
let destroy = 0;
|
|
90
|
+
let changes = 0;
|
|
91
|
+
for (const r of rc) {
|
|
92
|
+
const a = isObj(r) && isObj(r.change) && Array.isArray(r.change.actions) ? r.change.actions : [];
|
|
93
|
+
if (a.every((x) => x === "no-op" || x === "read"))
|
|
94
|
+
continue;
|
|
95
|
+
changes++;
|
|
96
|
+
if (a.includes("create"))
|
|
97
|
+
add++;
|
|
98
|
+
if (a.includes("delete"))
|
|
99
|
+
destroy++;
|
|
100
|
+
if (a.includes("update"))
|
|
101
|
+
change++;
|
|
102
|
+
}
|
|
103
|
+
return { add, change, destroy, changes, destroys: destroy };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* One member's part of the composed plan's `show` text: the text before the
|
|
107
|
+
* actions, each resource block of its module with `module.<m>.` taken off,
|
|
108
|
+
* its line of counts, and its outputs by their own names.
|
|
109
|
+
*/
|
|
110
|
+
export function sliceText(text, m, counts) {
|
|
111
|
+
const lines = text.split("\n");
|
|
112
|
+
const head = [];
|
|
113
|
+
const blocks = [];
|
|
114
|
+
const outs = [];
|
|
115
|
+
let i = 0;
|
|
116
|
+
for (; i < lines.length && !/^\s{2}# /.test(lines[i]); i++) {
|
|
117
|
+
if (/^(Plan:|No changes\.|Changes to Outputs:)/.test(lines[i]))
|
|
118
|
+
break;
|
|
119
|
+
head.push(lines[i]);
|
|
120
|
+
}
|
|
121
|
+
let cur;
|
|
122
|
+
for (; i < lines.length; i++) {
|
|
123
|
+
const l = lines[i];
|
|
124
|
+
if (/^\s{2}# /.test(l)) {
|
|
125
|
+
cur = [l];
|
|
126
|
+
blocks.push(cur);
|
|
127
|
+
}
|
|
128
|
+
else if (/^(Plan:|Changes to Outputs:|─|Note:|Saved the plan)/.test(l)) {
|
|
129
|
+
cur = undefined;
|
|
130
|
+
if (l.startsWith("Changes to Outputs:")) {
|
|
131
|
+
for (i++; i < lines.length && /^\s/.test(lines[i]); i++)
|
|
132
|
+
if (new RegExp(`^\\s+[-+~] ${m}__`).test(lines[i]))
|
|
133
|
+
outs.push(lines[i].replace(`${m}__`, ""));
|
|
134
|
+
i--;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (cur)
|
|
138
|
+
cur.push(l);
|
|
139
|
+
}
|
|
140
|
+
const mine = blocks
|
|
141
|
+
.filter((b) => topModule(b[0].replace(/^\s{2}# /, "")) === m)
|
|
142
|
+
.map((b) => [b[0].replace(`module.${m}.`, ""), ...b.slice(1)].join("\n").trimEnd());
|
|
143
|
+
const parts = [head.join("\n").trimEnd()];
|
|
144
|
+
if (mine.length === 0 && outs.length === 0)
|
|
145
|
+
parts.push("No changes. Its part of the composed run matches the configuration.");
|
|
146
|
+
else {
|
|
147
|
+
if (mine.length)
|
|
148
|
+
parts.push(mine.join("\n\n"));
|
|
149
|
+
parts.push(`Plan: ${counts.add} to add, ${counts.change} to change, ${counts.destroy} to destroy.`);
|
|
150
|
+
if (outs.length)
|
|
151
|
+
parts.push(`Changes to Outputs:\n${outs.join("\n")}`);
|
|
152
|
+
}
|
|
153
|
+
return parts.filter((p) => p !== "").join("\n\n") + "\n";
|
|
154
|
+
}
|
|
155
|
+
// ── reads between members ─────────────────────────────────────────────────
|
|
156
|
+
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
157
|
+
/**
|
|
158
|
+
* The names a root's files read off `data.<type>.<name>.<field>`, or
|
|
159
|
+
* undefined when they read the whole object. While the root is composed
|
|
160
|
+
* (./root.ts) a `terraform_remote_state` read is `var.chant_read_<name>`,
|
|
161
|
+
* which counts the same.
|
|
162
|
+
*/
|
|
163
|
+
function fieldsRead(dir, binary, type, name, field) {
|
|
164
|
+
const ref = type === "terraform_remote_state" ? `(?:data\\.${type}\\.|var\\.${READ_VAR_PREFIX})` : `data\\.${type}\\.`;
|
|
165
|
+
const re = new RegExp(`\\b${ref}${escapeRe(name)}(?![\\w-])(\\.${field}(?:\\.([A-Za-z_][\\w-]*)|\\[\\s*"([^"]+)"\\s*\\])?)?`, "g");
|
|
166
|
+
const read = new Set();
|
|
167
|
+
for (const t of dir ? rootTexts(dir, binary) : []) {
|
|
168
|
+
for (const hit of t.text.matchAll(re)) {
|
|
169
|
+
const out = hit[2] ?? hit[3];
|
|
170
|
+
if (!out)
|
|
171
|
+
return undefined;
|
|
172
|
+
read.add(out);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return read;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Each member's reads of other members, planned on the upstream's part of
|
|
179
|
+
* the composed plan: an output read that the upstream's planned outputs
|
|
180
|
+
* ({@link terraformPlannedOutputs} of its slice) leave unknown is named
|
|
181
|
+
* unknown. A `vars` read names its output; a `terraform_remote_state` or
|
|
182
|
+
* `terraform_estate_outputs` block's outputs are read from the member's own
|
|
183
|
+
* files, as terragucci's `outputsRead` and `estateValuesRead` did.
|
|
184
|
+
*/
|
|
185
|
+
export function composedReads(c, outputs) {
|
|
186
|
+
const out = new Map();
|
|
187
|
+
for (const member of c.members) {
|
|
188
|
+
const reads = [];
|
|
189
|
+
// Several `vars` reads of one upstream through one variable are one read.
|
|
190
|
+
const byKey = new Map();
|
|
191
|
+
for (const r of c.reads.get(member) ?? []) {
|
|
192
|
+
const planned = outputs.get(r.upstream);
|
|
193
|
+
if (!planned)
|
|
194
|
+
continue;
|
|
195
|
+
if (r.via === "vars") {
|
|
196
|
+
const key = `vars\u0000${r.upstream}\u0000${r.variable}`;
|
|
197
|
+
const had = byKey.get(key);
|
|
198
|
+
if (had)
|
|
199
|
+
had.outputs.add(r.output);
|
|
200
|
+
else
|
|
201
|
+
byKey.set(key, { r, outputs: new Set([r.output]) });
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
const read = r.via === "remote-state" ? fieldsRead(c.dirs.get(member), c.binary, "terraform_remote_state", r.name, "outputs") : fieldsRead(c.dirs.get(member), c.binary, "terraform_estate_outputs", r.name, "values");
|
|
205
|
+
byKey.set(`${r.via}\u0000${r.upstream}\u0000${r.name}`, { r, ...(read ? { outputs: read } : {}) });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const { r, outputs: read } of byKey.values()) {
|
|
209
|
+
const planned = outputs.get(r.upstream);
|
|
210
|
+
const unknown = [...new Set(planned.unknown)].filter((o) => read === undefined || read.has(o)).sort();
|
|
211
|
+
reads.push({ upstream: r.upstream, via: r.via, name: r.via === "vars" ? r.variable : r.name, ...(read ? { outputs: [...read].sort() } : {}), unknown });
|
|
212
|
+
}
|
|
213
|
+
if (reads.length)
|
|
214
|
+
out.set(member, reads);
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Every member's plan out of the composed plan's `show -json`, by component:
|
|
220
|
+
* {@link terraformChangeSetPart}, {@link terraformPlannedOutputs} and
|
|
221
|
+
* {@link terraformPlanShape} of its slice, so each member's part is the part
|
|
222
|
+
* a plan of its root alone gives on the same state. The member is the root's
|
|
223
|
+
* name (`Composition.roots`), as a single `terraform-apply` plan names it.
|
|
224
|
+
*/
|
|
225
|
+
export function composedMemberPlans(c, plan, options = {}) {
|
|
226
|
+
const slices = new Map(c.order.map((member) => [member, slicePlan(plan, c.modules.get(member))]));
|
|
227
|
+
const outputs = new Map(c.order.map((member) => [member, terraformPlannedOutputs(slices.get(member))]));
|
|
228
|
+
const reads = composedReads(c, outputs);
|
|
229
|
+
const result = {};
|
|
230
|
+
for (const member of c.order) {
|
|
231
|
+
const slice = slices.get(member);
|
|
232
|
+
const root = c.roots.get(member) ?? member;
|
|
233
|
+
const scope = options.scope?.(member);
|
|
234
|
+
const changeSet = terraformChangeSetPart({ member: root, plan: slice, ...(options.planner ? { planner: options.planner } : {}), ...(scope ? { scope } : {}) });
|
|
235
|
+
const mine = reads.get(member) ?? [];
|
|
236
|
+
const unknownInputs = [...new Set(mine.flatMap((r) => r.unknown.map((o) => `${r.upstream}.${o}`)))].sort();
|
|
237
|
+
result[member] = {
|
|
238
|
+
member: root,
|
|
239
|
+
planDigest: changeSet.member.planDigest ?? "",
|
|
240
|
+
changeSet,
|
|
241
|
+
outputs: outputs.get(member),
|
|
242
|
+
shape: terraformPlanShape(slice, root, { unknownInputs }),
|
|
243
|
+
slice,
|
|
244
|
+
counts: planCounts(slice),
|
|
245
|
+
reads: mine,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Where one state is: its bucket, when the backend names one, and its key. */
|
|
2
|
+
export interface StateKey {
|
|
3
|
+
bucket?: string;
|
|
4
|
+
key: string;
|
|
5
|
+
}
|
|
6
|
+
/** An address, or why the code does not say it. */
|
|
7
|
+
export type Addressed = StateKey | {
|
|
8
|
+
unresolved: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* One attribute as the code writes it: the string, `null` when it is written
|
|
12
|
+
* but is not a plain string (an expression, or a string with a template in
|
|
13
|
+
* it), undefined when it is not written.
|
|
14
|
+
*/
|
|
15
|
+
export type Attr = (name: string) => string | null | undefined;
|
|
16
|
+
/** The types this module gives an address of their own. */
|
|
17
|
+
export declare const ADDRESSED_TYPES: readonly ["local", "pg", "http", "consul", "kubernetes", "remote"];
|
|
18
|
+
/** A plain string with no template in it, else null. */
|
|
19
|
+
export declare function literal(v: unknown): string | null | undefined;
|
|
20
|
+
/** The host and database of a Postgres connection string, in URL or `key=value` form. */
|
|
21
|
+
export declare function pgDatabase(conn: string): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The address of a state of backend `type`, from its attributes. `dir` is the
|
|
24
|
+
* directory the binary runs in for the block (the root's, relative to the
|
|
25
|
+
* repo), which a local path is resolved against.
|
|
26
|
+
*/
|
|
27
|
+
export declare function stateAddress(type: string, get: Attr, dir: string): Addressed;
|
|
28
|
+
//# sourceMappingURL=state-address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-address.d.ts","sourceRoot":"","sources":["../../src/compose/state-address.ts"],"names":[],"mappings":"AA+BA,+EAA+E;AAC/E,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,mDAAmD;AACnD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/D,2DAA2D;AAC3D,eAAO,MAAM,eAAe,YAAI,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAU,CAAC;AAIlG,wDAAwD;AACxD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAG7D;AAaD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgB3D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CA+D5E"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifted from terragucci's `packages/terragucci/src/state-address.ts` at c493e0e
|
|
3
|
+
* (chant#4438), unchanged but for this note.
|
|
4
|
+
*
|
|
5
|
+
* Where a state is, for each backend type, as a root's code names it: in the
|
|
6
|
+
* root's own backend block (or `cloud` block), and in a
|
|
7
|
+
* `terraform_remote_state` block that reads it. Two roots line up when the
|
|
8
|
+
* address one's backend names is the address the other's read names.
|
|
9
|
+
*
|
|
10
|
+
* s3, gcs, azurerm and any type not named here keep the address they always
|
|
11
|
+
* had: the bucket, when one is named, and the key (or `prefix`). The others
|
|
12
|
+
* get a key of their own, prefixed with the type so that no two types share
|
|
13
|
+
* one:
|
|
14
|
+
*
|
|
15
|
+
* - `local:<path>`: the state file, resolved against the root's directory and
|
|
16
|
+
* written relative to the repo.
|
|
17
|
+
* - `pg:<host>/<database>/<schema>.<table>`: from `conn_str`, credentials left out.
|
|
18
|
+
* - `http:<address>`: the URL, credentials left out.
|
|
19
|
+
* - `consul:<address>/<path>`.
|
|
20
|
+
* - `kubernetes:<namespace>/<secret_suffix>`.
|
|
21
|
+
* - `remote:<hostname>/<organization>/<workspace>`: a `remote` backend or a `cloud` block.
|
|
22
|
+
*
|
|
23
|
+
* An address is unresolved when a part of it is not a plain string in the
|
|
24
|
+
* code: an expression such as `var.env`, or a value the backend takes from
|
|
25
|
+
* the environment or a `-backend-config` file (`PG_CONN_STR`,
|
|
26
|
+
* `TF_HTTP_ADDRESS`, `CONSUL_HTTP_ADDR`, `KUBE_NAMESPACE`,
|
|
27
|
+
* `TF_CLOUD_ORGANIZATION`, a workspace picked by tags or `TF_WORKSPACE`).
|
|
28
|
+
* Nothing can line it up with another root, so it is named instead.
|
|
29
|
+
*/
|
|
30
|
+
import { posix, sep } from "node:path";
|
|
31
|
+
/** The types this module gives an address of their own. */
|
|
32
|
+
export const ADDRESSED_TYPES = ["local", "pg", "http", "consul", "kubernetes", "remote"];
|
|
33
|
+
const unresolved = (why) => ({ unresolved: why });
|
|
34
|
+
/** A plain string with no template in it, else null. */
|
|
35
|
+
export function literal(v) {
|
|
36
|
+
if (v === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
return typeof v === "string" && !/\$\{|%\{/.test(v) ? v : null;
|
|
39
|
+
}
|
|
40
|
+
/** `scheme://user:pass@Host:port/path?q` as `host:port/path`, credentials and query left out. */
|
|
41
|
+
function urlAddress(raw, keepScheme) {
|
|
42
|
+
try {
|
|
43
|
+
const u = new URL(raw.includes("://") ? raw : `http://${raw}`);
|
|
44
|
+
const path = u.pathname.replace(/\/+$/, "");
|
|
45
|
+
return `${keepScheme ? `${u.protocol}//` : ""}${u.host.toLowerCase()}${path}`;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** The host and database of a Postgres connection string, in URL or `key=value` form. */
|
|
52
|
+
export function pgDatabase(conn) {
|
|
53
|
+
if (/^postgres(ql)?:\/\//i.test(conn)) {
|
|
54
|
+
try {
|
|
55
|
+
const u = new URL(conn);
|
|
56
|
+
const db = u.pathname.replace(/^\/+/, "") || u.searchParams.get("dbname");
|
|
57
|
+
const host = u.host.toLowerCase() || u.searchParams.get("host");
|
|
58
|
+
return host && db ? `${host}/${db}` : undefined;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const kv = new Map([...conn.matchAll(/(\w+)\s*=\s*('(?:[^'\\]|\\.)*'|\S+)/g)].map((m) => [m[1], m[2].replace(/^'|'$/g, "")]));
|
|
65
|
+
const host = kv.get("host")?.toLowerCase();
|
|
66
|
+
const db = kv.get("dbname");
|
|
67
|
+
if (!host || !db)
|
|
68
|
+
return undefined;
|
|
69
|
+
return `${host}${kv.get("port") ? `:${kv.get("port")}` : ""}/${db}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The address of a state of backend `type`, from its attributes. `dir` is the
|
|
73
|
+
* directory the binary runs in for the block (the root's, relative to the
|
|
74
|
+
* repo), which a local path is resolved against.
|
|
75
|
+
*/
|
|
76
|
+
export function stateAddress(type, get, dir) {
|
|
77
|
+
const missing = (name, from) => unresolved(get(name) === null ? `its ${type} ${name} is an expression, not a plain string` : `its ${type} backend names no ${name} in the code (${from ? `${from} or ` : ""}a -backend-config file supplies it)`);
|
|
78
|
+
switch (type) {
|
|
79
|
+
case "local": {
|
|
80
|
+
const path = get("path");
|
|
81
|
+
if (path === null)
|
|
82
|
+
return missing("path");
|
|
83
|
+
const p = (path ?? "terraform.tfstate").split(sep).join(posix.sep);
|
|
84
|
+
// Relative to the repo, `/` between parts; a path outside the repo keeps its `..`, an absolute one stays as it is.
|
|
85
|
+
return { key: `local:${posix.isAbsolute(p) ? posix.normalize(p) : posix.normalize(posix.join(dir.split(sep).join(posix.sep) || ".", p))}` };
|
|
86
|
+
}
|
|
87
|
+
case "pg": {
|
|
88
|
+
const conn = get("conn_str");
|
|
89
|
+
if (!conn)
|
|
90
|
+
return missing("conn_str", "PG_CONN_STR");
|
|
91
|
+
const db = pgDatabase(conn);
|
|
92
|
+
if (!db)
|
|
93
|
+
return unresolved("its pg conn_str names no host and database");
|
|
94
|
+
const schema = get("schema_name");
|
|
95
|
+
const table = get("table_name");
|
|
96
|
+
if (schema === null)
|
|
97
|
+
return missing("schema_name");
|
|
98
|
+
if (table === null)
|
|
99
|
+
return missing("table_name");
|
|
100
|
+
return { key: `pg:${db}/${schema ?? "terraform_remote_state"}.${table ?? "states"}` };
|
|
101
|
+
}
|
|
102
|
+
case "http": {
|
|
103
|
+
const address = get("address");
|
|
104
|
+
if (!address)
|
|
105
|
+
return missing("address", "TF_HTTP_ADDRESS");
|
|
106
|
+
const url = urlAddress(address, true);
|
|
107
|
+
return url ? { key: `http:${url}` } : unresolved(`its http address is not a URL`);
|
|
108
|
+
}
|
|
109
|
+
case "consul": {
|
|
110
|
+
const address = get("address");
|
|
111
|
+
const path = get("path");
|
|
112
|
+
if (!path)
|
|
113
|
+
return missing("path");
|
|
114
|
+
if (!address)
|
|
115
|
+
return missing("address", "CONSUL_HTTP_ADDR");
|
|
116
|
+
const host = urlAddress(address, false);
|
|
117
|
+
return host ? { key: `consul:${host}/${path.replace(/^\/+/, "")}` } : unresolved("its consul address is not a host");
|
|
118
|
+
}
|
|
119
|
+
case "kubernetes": {
|
|
120
|
+
const suffix = get("secret_suffix");
|
|
121
|
+
const namespace = get("namespace");
|
|
122
|
+
if (!suffix)
|
|
123
|
+
return missing("secret_suffix");
|
|
124
|
+
if (!namespace)
|
|
125
|
+
return missing("namespace", "KUBE_NAMESPACE");
|
|
126
|
+
return { key: `kubernetes:${namespace}/${suffix}` };
|
|
127
|
+
}
|
|
128
|
+
case "remote":
|
|
129
|
+
case "cloud": {
|
|
130
|
+
const host = get("hostname");
|
|
131
|
+
const org = get("organization");
|
|
132
|
+
const name = get("name");
|
|
133
|
+
if (host === null)
|
|
134
|
+
return missing("hostname");
|
|
135
|
+
if (!org)
|
|
136
|
+
return missing("organization", type === "cloud" ? "TF_CLOUD_ORGANIZATION" : undefined);
|
|
137
|
+
if (name === null)
|
|
138
|
+
return unresolved(`its ${type} workspace name is an expression, not a plain string`);
|
|
139
|
+
if (name === undefined)
|
|
140
|
+
return unresolved(`its ${type} workspaces block names no workspace by name (one picked by tags, prefix or TF_WORKSPACE cannot be read from the code)`);
|
|
141
|
+
return { key: `remote:${(host ?? "app.terraform.io").toLowerCase()}/${org}/${name}` };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// s3, gcs, azurerm, and the types not named above: the bucket and key, as before.
|
|
145
|
+
const k = get("key");
|
|
146
|
+
const p = get("prefix");
|
|
147
|
+
const key = k || p;
|
|
148
|
+
if (!key)
|
|
149
|
+
return missing(k === null ? "key" : p === null ? "prefix" : type === "gcs" ? "prefix" : "key");
|
|
150
|
+
const bucket = get("bucket");
|
|
151
|
+
if (bucket === null)
|
|
152
|
+
return missing("bucket");
|
|
153
|
+
return { ...(bucket ? { bucket } : {}), key };
|
|
154
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The working state of a composed run (chant#4442, epic #4419): each
|
|
3
|
+
* member's pulled state moved under `module.<m>` in one state the composed
|
|
4
|
+
* root plans and applies against, and, once the apply is done or has failed,
|
|
5
|
+
* split back into one state per member by module address.
|
|
6
|
+
*
|
|
7
|
+
* Lifted from terragucci's `packages/terragucci/src/compose.ts` at c493e0e
|
|
8
|
+
* (`mergeStates`, `splitState`) and `migrate.ts` (`derivedLineage`), with
|
|
9
|
+
* chant's {@link Composition} in place of terragucci's: members are
|
|
10
|
+
* components, and a member's directory is `Composition.dirs`. Pulling and
|
|
11
|
+
* writing the states is `../state` (#4437).
|
|
12
|
+
*
|
|
13
|
+
* The lineage and serial rules are terragucci's: a split state keeps its
|
|
14
|
+
* pulled lineage and takes the pulled serial plus one; a member with no
|
|
15
|
+
* state yet gets a lineage derived from the composed run and its root, and
|
|
16
|
+
* serial 1. The working state itself has serial 1 and a lineage derived from
|
|
17
|
+
* the members in order.
|
|
18
|
+
*/
|
|
19
|
+
import type { Composition } from "../compose.js";
|
|
20
|
+
import type { StateFile } from "../state/exec.js";
|
|
21
|
+
/** What the derived lineages are derived from, beside the roots. */
|
|
22
|
+
export declare const COMPOSE_LINEAGE = "chant terraform.compose";
|
|
23
|
+
/** A lineage in the form Terraform writes (a version 4 UUID), derived from `parts`, so the same parts always give the same lineage. */
|
|
24
|
+
export declare function derivedLineage(...parts: string[]): string;
|
|
25
|
+
/** The members whose state the working state holds, in apply order. */
|
|
26
|
+
type StateComposition = Pick<Composition, "order" | "modules" | "dirs"> & Partial<Pick<Composition, "roots" | "binary">>;
|
|
27
|
+
/**
|
|
28
|
+
* The working state: each member's resources with `module.<m>` in front of
|
|
29
|
+
* their module, each output as `<m>__<name>` (the composed root's outputs, so
|
|
30
|
+
* an output that does not change plans no change), check results left out.
|
|
31
|
+
* A resource whose root configures its provider itself names the module's
|
|
32
|
+
* provider configuration. `pulled` is by member; a member with no state
|
|
33
|
+
* (null or absent) adds nothing. The highest `terraform_version` pulled wins.
|
|
34
|
+
*/
|
|
35
|
+
export declare function mergeStates(c: StateComposition, pulled: ReadonlyMap<string, StateFile | null>): StateFile;
|
|
36
|
+
/** One member's state out of the working state, and whether it holds what was pulled. */
|
|
37
|
+
export interface SplitState {
|
|
38
|
+
state: StateFile;
|
|
39
|
+
/** It holds what was pulled (for a member with no state: nothing), so there is nothing to write. */
|
|
40
|
+
same: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* One member's state out of the working state: its resources with the module
|
|
44
|
+
* taken off, its outputs from `<m>__*`, its pulled lineage and its pulled
|
|
45
|
+
* serial plus one (a member with no state yet gets a lineage of its own,
|
|
46
|
+
* derived from its root, and serial 1). `same` when it holds what was pulled.
|
|
47
|
+
*/
|
|
48
|
+
export declare function splitState(working: StateFile, c: StateComposition, member: string, pulled: StateFile | null): SplitState;
|
|
49
|
+
/** Every member's split state, by member, in apply order. */
|
|
50
|
+
export declare function splitStates(working: StateFile, c: StateComposition, pulled: ReadonlyMap<string, StateFile | null>): Map<string, SplitState>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=state-merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-merge.d.ts","sourceRoot":"","sources":["../../src/compose/state-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,eAAe,CAAC;AAI9D,oEAAoE;AACpE,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD,uIAAuI;AACvI,wBAAgB,cAAc,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAGzD;AAeD,uEAAuE;AACvE,KAAK,gBAAgB,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC;AAEzH;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,CAsBzG;AA0BD,yFAAyF;AACzF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,CAAC;IACjB,oGAAoG;IACpG,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,UAAU,CAuBxH;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,gBAAgB,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAE3I"}
|