@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
|
@@ -45,12 +45,16 @@ import { tmpdir } from "node:os";
|
|
|
45
45
|
import { promisify } from "node:util";
|
|
46
46
|
import { resolve, dirname, join, relative, sep } from "node:path";
|
|
47
47
|
import { loadChantConfigUpward } from "@intentius/chant/config";
|
|
48
|
+
import { findWorkspaceRoot } from "@intentius/chant/project-root";
|
|
48
49
|
import { liveReadKey, memoLiveRead } from "@intentius/chant/live-read-session";
|
|
49
50
|
import { terraformPlanDigest } from "../../plan-digest";
|
|
50
51
|
import { choudoufuSetPlanParts, plannerForBinary, terraformChangeSetPart } from "../../change-set";
|
|
51
52
|
import type { ChangeSetPart } from "@intentius/chant/change-set";
|
|
52
53
|
import type { TerraformConfig, TerraformRootConfig } from "../../config";
|
|
53
54
|
import { detectLiveEstate } from "./live-detect";
|
|
55
|
+
import { backendConfigValues } from "../../backend-config";
|
|
56
|
+
import { lockTimeoutArgs } from "../../lock-timeout";
|
|
57
|
+
import { coneArgs, readPlanCone, type PlanCone } from "../../cone";
|
|
54
58
|
import {
|
|
55
59
|
parseAdoptionCommands,
|
|
56
60
|
readAdoptionLedger,
|
|
@@ -116,6 +120,36 @@ export const MIN_CHOUDOUFU_VERSION = "0.15.0";
|
|
|
116
120
|
*/
|
|
117
121
|
export const MIN_CHOUDOUFU_WAVES_VERSION = "0.22.0";
|
|
118
122
|
|
|
123
|
+
/**
|
|
124
|
+
* The choudoufu release a composed run of estates needs (#4445): a root with
|
|
125
|
+
* no `live` block that calls estate directories as modules, planned and
|
|
126
|
+
* applied as one walk, with a `terraform_estate_outputs` read of another
|
|
127
|
+
* estate in the run answered inside it (choudoufu#2059, first released in
|
|
128
|
+
* v0.31.0). Only the composed estate run (`compose/estate.ts`) checks it;
|
|
129
|
+
* below it the members plan wave by wave. A dev build names no release and
|
|
130
|
+
* passes, as for the other floors.
|
|
131
|
+
*/
|
|
132
|
+
export const MIN_CHOUDOUFU_ESTATES_VERSION = "0.31.0";
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The choudoufu release whose `live-graph -json -from-plan=<file>` prints the
|
|
136
|
+
* engine graph document (chant#4520's design section 4, choudoufu#2285), the
|
|
137
|
+
* one `describeResources()` reads engine facts from on a live root
|
|
138
|
+
* (chant#4528). choudoufu's changelog lists the command under
|
|
139
|
+
* `v0.32.0 (Unreleased)`, so this is the version it releases as. The chant
|
|
140
|
+
* side of the same contract, the first chant that writes those facts, is
|
|
141
|
+
* `ENGINE_FACTS_FLOOR` in core's engine-facts.ts, which is NEXT_RELEASE
|
|
142
|
+
* until the cut.
|
|
143
|
+
*
|
|
144
|
+
* Not a refusal. Facts are for people and never feed a decision, so a
|
|
145
|
+
* choudoufu without the command (a usage error, see
|
|
146
|
+
* {@link classifyLiveGraphFailure}) leaves `facts` absent with one note
|
|
147
|
+
* naming this version, and the rest of the read is unchanged. The check is
|
|
148
|
+
* the capability, not the version string: a local or dev build names a
|
|
149
|
+
* version below this or none at all, and still carries the command.
|
|
150
|
+
*/
|
|
151
|
+
export const MIN_CHOUDOUFU_GRAPH_VERSION = "0.32.0";
|
|
152
|
+
|
|
119
153
|
/**
|
|
120
154
|
* Where a choudoufu root's wave files live, relative to the project root:
|
|
121
155
|
* `<root>/plan-set.json` (the set plan document chant planned and the
|
|
@@ -163,6 +197,14 @@ export interface TerraformRootArgs {
|
|
|
163
197
|
* `process.cwd()`, which is the project root under `chant run`.
|
|
164
198
|
*/
|
|
165
199
|
cwd?: string;
|
|
200
|
+
/**
|
|
201
|
+
* The directory the root's files are read from in place of the entry's
|
|
202
|
+
* `dir`, relative to the project root (chant#4542). A promote or rollback
|
|
203
|
+
* under a release sets it to the release's recorded copy of the root; the
|
|
204
|
+
* entry's workspace, var files, backend config and estate still apply, and
|
|
205
|
+
* its var files and backend-config files resolve against this directory.
|
|
206
|
+
*/
|
|
207
|
+
dir?: string;
|
|
166
208
|
}
|
|
167
209
|
|
|
168
210
|
export interface TerraformInitArgs extends TerraformRootArgs {
|
|
@@ -191,6 +233,27 @@ export interface TerraformPlanArgs extends TerraformRootArgs {
|
|
|
191
233
|
* of that file changes nothing else.
|
|
192
234
|
*/
|
|
193
235
|
targets?: string[];
|
|
236
|
+
/**
|
|
237
|
+
* `false` skips `show -no-color`, the human-readable render (#4479). The
|
|
238
|
+
* plan then runs one `show` process, `show -json`, whose document gives the
|
|
239
|
+
* digest, the change set and everything a caller derives from `json`, and
|
|
240
|
+
* {@link TerraformPlanResult.text} is `""`. For a caller that never reads
|
|
241
|
+
* the text, such as the `terraform-apply` capability. Default: `true`.
|
|
242
|
+
*/
|
|
243
|
+
text?: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* How long the plan waits for another run's state lock (#4545), passed as
|
|
246
|
+
* `-lock-timeout` unless `TF_CLI_ARGS` or `TF_CLI_ARGS_plan` names one.
|
|
247
|
+
* Default: no flag, terraform's own (no wait).
|
|
248
|
+
*/
|
|
249
|
+
lockTimeout?: string;
|
|
250
|
+
/**
|
|
251
|
+
* choudoufu only (#4545): plan the cone of the change since this revision
|
|
252
|
+
* (`-cone=<base>`) on a root under a `live` block that is not an estate
|
|
253
|
+
* file. Any other root, binary, or a plan with `targets` or `destroy`,
|
|
254
|
+
* plans in full. {@link TerraformPlanResult.cone} says which it was.
|
|
255
|
+
*/
|
|
256
|
+
cone?: string;
|
|
194
257
|
}
|
|
195
258
|
|
|
196
259
|
export interface TerraformApplyArgs extends TerraformRootArgs {
|
|
@@ -211,6 +274,8 @@ export interface TerraformApplyArgs extends TerraformRootArgs {
|
|
|
211
274
|
* separate to pass.
|
|
212
275
|
*/
|
|
213
276
|
planFile?: string;
|
|
277
|
+
/** How long the apply waits for another run's state lock (#4545), as {@link TerraformPlanArgs.lockTimeout}. */
|
|
278
|
+
lockTimeout?: string;
|
|
214
279
|
}
|
|
215
280
|
|
|
216
281
|
export interface TerraformShowArgs extends TerraformRootArgs {
|
|
@@ -280,6 +345,13 @@ export interface TerraformInitResult {
|
|
|
280
345
|
dir: string;
|
|
281
346
|
/** Workspace the run selected via `TF_WORKSPACE`, when the root names one. */
|
|
282
347
|
workspace?: string;
|
|
348
|
+
/**
|
|
349
|
+
* The root module directory relative to the chant workspace root, with `/`
|
|
350
|
+
* separators (chant#4482), when the root sits inside a workspace. A
|
|
351
|
+
* TerraformApplyOp publishes it as the `TerraformRootPath` run outcome, so a
|
|
352
|
+
* ledger read can name the member whose directory holds the root it applied.
|
|
353
|
+
*/
|
|
354
|
+
rootPath?: string;
|
|
283
355
|
}
|
|
284
356
|
|
|
285
357
|
/** Counts projected out of a plan's `resource_changes`. */
|
|
@@ -304,7 +376,7 @@ export interface TerraformPlanResult extends PlanChangeCounts {
|
|
|
304
376
|
dir: string;
|
|
305
377
|
/** `terraform show -json <planFile>`, parsed. */
|
|
306
378
|
json: unknown;
|
|
307
|
-
/** `terraform show -no-color <planFile>` — the human-readable plan. */
|
|
379
|
+
/** `terraform show -no-color <planFile>` — the human-readable plan. `""` when the plan ran with `text: false`. */
|
|
308
380
|
text: string;
|
|
309
381
|
/**
|
|
310
382
|
* This plan's identity (#2300) — {@link terraformPlanDigest} over
|
|
@@ -320,6 +392,8 @@ export interface TerraformPlanResult extends PlanChangeCounts {
|
|
|
320
392
|
* `composeChangeSet` and bind the run's gate to the document's digest.
|
|
321
393
|
*/
|
|
322
394
|
changeSet: ChangeSetPart;
|
|
395
|
+
/** Set when the plan was asked for a cone (#4545): the cone it planned, or why it planned the whole estate. */
|
|
396
|
+
cone?: PlanCone;
|
|
323
397
|
}
|
|
324
398
|
|
|
325
399
|
/**
|
|
@@ -537,19 +611,24 @@ export function terraformEnvironment(root?: Pick<TerraformRootConfig, "workspace
|
|
|
537
611
|
};
|
|
538
612
|
}
|
|
539
613
|
|
|
540
|
-
/**
|
|
614
|
+
/**
|
|
615
|
+
* `terraform init`, with the root's `backendConfigFiles` as
|
|
616
|
+
* `-backend-config=<path>` flags and then its `backendConfig` as
|
|
617
|
+
* `-backend-config=k=v` flags (chant#4459): init applies later flags over
|
|
618
|
+
* earlier ones, so a pair overrides a file. A path is passed as written; init
|
|
619
|
+
* runs in the root's directory, which a relative one resolves against.
|
|
620
|
+
*/
|
|
541
621
|
export function terraformInitCommand(opts: {
|
|
542
622
|
binary: string;
|
|
543
623
|
backendConfig?: Record<string, string>;
|
|
624
|
+
backendConfigFiles?: readonly string[];
|
|
544
625
|
upgrade?: boolean;
|
|
545
626
|
reconfigure?: boolean;
|
|
546
627
|
}): string {
|
|
547
628
|
const parts = [opts.binary, "init", "-input=false"];
|
|
548
629
|
if (opts.upgrade) parts.push("-upgrade");
|
|
549
630
|
if (opts.reconfigure) parts.push("-reconfigure");
|
|
550
|
-
for (const
|
|
551
|
-
parts.push(`-backend-config=${quoteArg(`${key}=${value}`)}`);
|
|
552
|
-
}
|
|
631
|
+
for (const value of backendConfigValues(opts)) parts.push(`-backend-config=${quoteArg(value)}`);
|
|
553
632
|
return parts.join(" ");
|
|
554
633
|
}
|
|
555
634
|
|
|
@@ -565,9 +644,12 @@ export function terraformPlanCommand(opts: {
|
|
|
565
644
|
vars?: Record<string, unknown>;
|
|
566
645
|
destroy?: boolean;
|
|
567
646
|
targets?: string[];
|
|
647
|
+
/** Extra flags after the fixed ones (#4545): `-lock-timeout`, `-cone`. */
|
|
648
|
+
extra?: readonly string[];
|
|
568
649
|
}): string {
|
|
569
650
|
const parts = [opts.binary, "plan", "-input=false", "-detailed-exitcode"];
|
|
570
651
|
if (opts.destroy) parts.push("-destroy");
|
|
652
|
+
for (const flag of opts.extra ?? []) parts.push(quoteArg(flag));
|
|
571
653
|
for (const target of [...new Set(opts.targets ?? [])].sort()) parts.push(`-target=${quoteArg(target)}`);
|
|
572
654
|
for (const varFile of opts.varFiles ?? []) parts.push(`-var-file=${quoteArg(varFile)}`);
|
|
573
655
|
for (const [name, value] of Object.entries(opts.vars ?? {}).sort(([a], [b]) => a.localeCompare(b))) {
|
|
@@ -584,8 +666,9 @@ export function terraformPlanCommand(opts: {
|
|
|
584
666
|
* block, and a matched one applies without re-prompting, exactly as stock's
|
|
585
667
|
* own `apply <planfile>` does, so no `-auto-approve` is needed or passed.
|
|
586
668
|
*/
|
|
587
|
-
export function terraformApplyCommand(opts: { binary: string; planFile: string }): string {
|
|
588
|
-
|
|
669
|
+
export function terraformApplyCommand(opts: { binary: string; planFile: string; extra?: readonly string[] }): string {
|
|
670
|
+
const extra = (opts.extra ?? []).map((f) => ` ${quoteArg(f)}`).join("");
|
|
671
|
+
return `${opts.binary} apply -input=false${extra} ${quoteArg(opts.planFile)}`;
|
|
589
672
|
}
|
|
590
673
|
|
|
591
674
|
/**
|
|
@@ -629,6 +712,37 @@ export function choudoufuLivePlanCommand(opts: {
|
|
|
629
712
|
return parts.join(" ");
|
|
630
713
|
}
|
|
631
714
|
|
|
715
|
+
/**
|
|
716
|
+
* `live-graph -json -from-plan=<file> [-estate=<estate>]` (choudoufu#2285).
|
|
717
|
+
* No `DIR` argument: like {@link choudoufuLiveCheckCommand}, the activity
|
|
718
|
+
* runs in the root directory, which is DIR's default. `-estate` follows
|
|
719
|
+
* {@link choudoufuLivePlanCommand}'s rule: only for a root that does not
|
|
720
|
+
* name its own estate. `-history` is never passed: record versions take a
|
|
721
|
+
* listing per record and `s3:ListBucketVersions`, and an observation read
|
|
722
|
+
* has no use for them (the #4520 ruling, Q6: opt-in).
|
|
723
|
+
*/
|
|
724
|
+
export function choudoufuLiveGraphCommand(opts: { binary: string; fromPlan: string; estate?: string }): string {
|
|
725
|
+
const parts = [opts.binary, "live-graph", "-json", `-from-plan=${quoteArg(opts.fromPlan)}`];
|
|
726
|
+
if (opts.estate !== undefined) parts.push(`-estate=${quoteArg(opts.estate)}`);
|
|
727
|
+
return parts.join(" ");
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Whether a failed `live-graph` run is a choudoufu that has no such command
|
|
732
|
+
* or flag (`"unsupported"`), or a real failure (`"failed"`). Older builds
|
|
733
|
+
* answer an unknown command two ways: the new CLI prints `OpenTofu has no
|
|
734
|
+
* command named "live-graph"` and exits 1 (cmd/choudoufu/command_main.go),
|
|
735
|
+
* and the older mitchellh/cli path prints its usage and exits 127. A build
|
|
736
|
+
* whose `live-graph` predates `-from-plan` fails the flag parse with `flag
|
|
737
|
+
* provided but not defined`.
|
|
738
|
+
*/
|
|
739
|
+
export function classifyLiveGraphFailure(code: unknown, output: string): "unsupported" | "failed" {
|
|
740
|
+
if (code === 127) return "unsupported";
|
|
741
|
+
if (/no command named "?live-graph"?/i.test(output)) return "unsupported";
|
|
742
|
+
if (/flag provided but not defined: -(?:from-plan|json|estate)\b/.test(output)) return "unsupported";
|
|
743
|
+
return "failed";
|
|
744
|
+
}
|
|
745
|
+
|
|
632
746
|
/** `live-ls -estate=<estate> -json [-consistent]`. */
|
|
633
747
|
export function choudoufuLiveLsCommand(opts: { binary: string; estate: string; consistent?: boolean }): string {
|
|
634
748
|
const parts = [opts.binary, "live-ls", `-estate=${quoteArg(opts.estate)}`, "-json"];
|
|
@@ -854,7 +968,7 @@ async function resolveRoot(args: TerraformRootArgs, signal?: AbortSignal): Promi
|
|
|
854
968
|
);
|
|
855
969
|
}
|
|
856
970
|
const binary = terraformBinary(namespace);
|
|
857
|
-
const dir = resolve(projectRoot, root.dir);
|
|
971
|
+
const dir = resolve(projectRoot, args.dir ?? root.dir);
|
|
858
972
|
await ensureChoudoufuVersion(binary, signal);
|
|
859
973
|
const estate = binary === "choudoufu" ? detectLiveEstate(dir) : undefined;
|
|
860
974
|
// `estate` stays what it has always been: the estate the root's own HCL
|
|
@@ -917,8 +1031,8 @@ function report(stdout: string, stderr: string): void {
|
|
|
917
1031
|
// ── Activities ──────────────────────────────────────────────────────────────
|
|
918
1032
|
|
|
919
1033
|
/**
|
|
920
|
-
* `terraform init` in the named root, with the root's `
|
|
921
|
-
* as `-backend-config` flags. Uses the longInfra profile: init downloads
|
|
1034
|
+
* `terraform init` in the named root, with the root's `backendConfigFiles` and
|
|
1035
|
+
* `backendConfig` supplied as `-backend-config` flags. Uses the longInfra profile: init downloads
|
|
922
1036
|
* providers and modules, a network call of unpredictable size.
|
|
923
1037
|
*/
|
|
924
1038
|
export async function terraformInit(
|
|
@@ -929,19 +1043,55 @@ export async function terraformInit(
|
|
|
929
1043
|
const cmd = terraformInitCommand({
|
|
930
1044
|
binary,
|
|
931
1045
|
...(root.backendConfig ? { backendConfig: root.backendConfig } : {}),
|
|
1046
|
+
...(root.backendConfigFiles ? { backendConfigFiles: root.backendConfigFiles } : {}),
|
|
932
1047
|
...(args.upgrade ? { upgrade: true } : {}),
|
|
933
1048
|
...(args.reconfigure ? { reconfigure: true } : {}),
|
|
934
1049
|
});
|
|
935
1050
|
|
|
936
|
-
|
|
937
|
-
|
|
1051
|
+
// Known once the root resolves, before init runs (chant#4512), so a failed
|
|
1052
|
+
// init still publishes them and the ledger names the root it was for.
|
|
1053
|
+
const rootPath = workspaceRelativePath(dir);
|
|
1054
|
+
const result: TerraformInitResult = { dir, ...(root.workspace ? { workspace: root.workspace } : {}), ...(rootPath !== undefined ? { rootPath } : {}) };
|
|
1055
|
+
|
|
1056
|
+
let out: { stdout: string; stderr: string };
|
|
1057
|
+
try {
|
|
1058
|
+
out = await run(cmd, dir, terraformEnvironment(root), signal);
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
throw withKnownOutputs(err, result);
|
|
1061
|
+
}
|
|
1062
|
+
report(out.stdout, out.stderr);
|
|
1063
|
+
return result;
|
|
1064
|
+
}
|
|
938
1065
|
|
|
939
|
-
|
|
1066
|
+
/**
|
|
1067
|
+
* `err` carrying `outputs` as the outputs the activity knew when it failed
|
|
1068
|
+
* (chant#4512): the `knownOutputs` property core's executor reads a failed
|
|
1069
|
+
* step's outcome attributes from (core's `withKnownOutputs`). It is set here
|
|
1070
|
+
* rather than imported so the lexicon needs no newer core; an older executor
|
|
1071
|
+
* reads the error as any other failure.
|
|
1072
|
+
*/
|
|
1073
|
+
function withKnownOutputs(err: unknown, outputs: object): Error {
|
|
1074
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
1075
|
+
return Object.assign(e, { knownOutputs: outputs });
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
/**
|
|
1079
|
+
* `dir` relative to the chant workspace that holds it, `/`-separated, or
|
|
1080
|
+
* undefined outside a workspace or outside its root (chant#4482). The
|
|
1081
|
+
* workspace root `"."` stands for itself.
|
|
1082
|
+
*/
|
|
1083
|
+
export function workspaceRelativePath(dir: string): string | undefined {
|
|
1084
|
+
const found = findWorkspaceRoot(dir);
|
|
1085
|
+
if (!found) return undefined;
|
|
1086
|
+
const rel = relative(found.dir, dir);
|
|
1087
|
+
if (rel.startsWith("..")) return undefined;
|
|
1088
|
+
return rel === "" ? "." : rel.split(sep).join("/");
|
|
940
1089
|
}
|
|
941
1090
|
|
|
942
1091
|
/**
|
|
943
1092
|
* `terraform plan -detailed-exitcode -out=<planFile>` in the named root, then
|
|
944
|
-
* `terraform show` over the written plan in both `-json` and `-no-color` form
|
|
1093
|
+
* `terraform show` over the written plan in both `-json` and `-no-color` form
|
|
1094
|
+
* (`-json` alone with `text: false`).
|
|
945
1095
|
*
|
|
946
1096
|
* The exit code is the answer, not an error condition: 0 is a plan with no
|
|
947
1097
|
* changes, 2 is a plan with changes, and anything else, 1 included, is a
|
|
@@ -956,9 +1106,13 @@ export async function terraformPlan(
|
|
|
956
1106
|
args: TerraformPlanArgs,
|
|
957
1107
|
signal?: AbortSignal,
|
|
958
1108
|
): Promise<TerraformPlanResult> {
|
|
959
|
-
const { binary, root, dir } = await resolveRoot(args, signal);
|
|
1109
|
+
const { binary, root, dir, live } = await resolveRoot(args, signal);
|
|
960
1110
|
const planFile = args.planFile ?? DEFAULT_PLAN_FILE;
|
|
961
1111
|
const env = terraformEnvironment(root);
|
|
1112
|
+
const lock = args.lockTimeout !== undefined ? lockTimeoutArgs("plan", args.lockTimeout) : [];
|
|
1113
|
+
// #4545: a cone only on a live root that is not an estate file; -target and -destroy plan in full.
|
|
1114
|
+
const fixed = [...(args.destroy ? ["-destroy"] : []), ...((args.targets ?? []).length > 0 ? ["-target"] : [])];
|
|
1115
|
+
const cone = args.cone !== undefined ? coneArgs(binary, args.cone, fixed, live && !existsSync(join(dir, "estate.chdf.hcl"))) : [];
|
|
962
1116
|
const cmd = terraformPlanCommand({
|
|
963
1117
|
binary,
|
|
964
1118
|
planFile,
|
|
@@ -966,12 +1120,15 @@ export async function terraformPlan(
|
|
|
966
1120
|
...(args.vars ? { vars: args.vars } : {}),
|
|
967
1121
|
...(args.destroy ? { destroy: true } : {}),
|
|
968
1122
|
...(args.targets && args.targets.length > 0 ? { targets: args.targets } : {}),
|
|
1123
|
+
...(cone.length + lock.length > 0 ? { extra: [...cone, ...lock] } : {}),
|
|
969
1124
|
});
|
|
970
1125
|
|
|
971
1126
|
let changed: boolean;
|
|
1127
|
+
let output = "";
|
|
972
1128
|
try {
|
|
973
1129
|
const { stdout, stderr } = await run(cmd, dir, env, signal);
|
|
974
1130
|
report(stdout, stderr);
|
|
1131
|
+
output = `${stdout}\n${stderr}`;
|
|
975
1132
|
changed = false;
|
|
976
1133
|
} catch (err) {
|
|
977
1134
|
// An abort or a spawn failure carries no numeric exit code. That is not
|
|
@@ -985,11 +1142,12 @@ export async function terraformPlan(
|
|
|
985
1142
|
);
|
|
986
1143
|
}
|
|
987
1144
|
report(failure.stdout ?? "", failure.stderr ?? "");
|
|
1145
|
+
output = `${failure.stdout ?? ""}\n${failure.stderr ?? ""}`;
|
|
988
1146
|
changed = true;
|
|
989
1147
|
}
|
|
990
1148
|
|
|
991
1149
|
const jsonRun = await run(terraformShowCommand({ binary, json: true, planFile }), dir, env, signal);
|
|
992
|
-
const
|
|
1150
|
+
const text = args.text === false ? "" : (await run(terraformShowCommand({ binary, json: false, planFile }), dir, env, signal)).stdout;
|
|
993
1151
|
const json: unknown = JSON.parse(jsonRun.stdout);
|
|
994
1152
|
|
|
995
1153
|
return {
|
|
@@ -997,7 +1155,7 @@ export async function terraformPlan(
|
|
|
997
1155
|
planFile,
|
|
998
1156
|
dir,
|
|
999
1157
|
json,
|
|
1000
|
-
text
|
|
1158
|
+
text,
|
|
1001
1159
|
planDigest: terraformPlanDigest(json),
|
|
1002
1160
|
changeSet: terraformChangeSetPart({
|
|
1003
1161
|
member: args.root,
|
|
@@ -1006,6 +1164,7 @@ export async function terraformPlan(
|
|
|
1006
1164
|
...((root.estate ?? root.workspace) ? { scope: root.estate ?? root.workspace } : {}),
|
|
1007
1165
|
}),
|
|
1008
1166
|
...countPlanChanges(json),
|
|
1167
|
+
...(cone.length > 0 ? { cone: readPlanCone(output, join(dir, planFile), args.cone!) } : {}),
|
|
1009
1168
|
};
|
|
1010
1169
|
}
|
|
1011
1170
|
|
|
@@ -1057,7 +1216,8 @@ export async function terraformApply(
|
|
|
1057
1216
|
}
|
|
1058
1217
|
|
|
1059
1218
|
const planFile = args.planFile!;
|
|
1060
|
-
const
|
|
1219
|
+
const lock = args.lockTimeout !== undefined ? lockTimeoutArgs("apply", args.lockTimeout) : [];
|
|
1220
|
+
const cmd = terraformApplyCommand({ binary, planFile, ...(lock.length > 0 ? { extra: lock } : {}) });
|
|
1061
1221
|
|
|
1062
1222
|
try {
|
|
1063
1223
|
const { stdout, stderr } = await run(cmd, dir, terraformEnvironment(root), signal);
|
|
@@ -1092,7 +1252,11 @@ export async function terraformOutputs(
|
|
|
1092
1252
|
args: TerraformRootArgs,
|
|
1093
1253
|
signal?: AbortSignal,
|
|
1094
1254
|
): Promise<Record<string, unknown>> {
|
|
1095
|
-
|
|
1255
|
+
return outputsIn(await resolveRoot(args, signal), signal);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
/** `<binary> output -json` in a resolved root, as `{ name: value }`. */
|
|
1259
|
+
async function outputsIn({ binary, root, dir }: ResolvedRoot, signal?: AbortSignal): Promise<Record<string, unknown>> {
|
|
1096
1260
|
const { stdout } = await run(`${binary} output -json`, dir, terraformEnvironment(root), signal);
|
|
1097
1261
|
const parsed = JSON.parse(stdout || "{}") as Record<string, { value?: unknown }>;
|
|
1098
1262
|
return Object.fromEntries(Object.entries(parsed).map(([name, entry]) => [name, entry?.value]));
|
|
@@ -1174,7 +1338,7 @@ export async function choudoufuWaveRoot(
|
|
|
1174
1338
|
if (resolved.root.varFiles && resolved.root.varFiles.length > 0) {
|
|
1175
1339
|
return { wave: false, reason: "the root has var files, which live-plan-set does not take" };
|
|
1176
1340
|
}
|
|
1177
|
-
if (resolved.root.backendConfig && Object.keys(resolved.root.backendConfig).length > 0) {
|
|
1341
|
+
if ((resolved.root.backendConfig && Object.keys(resolved.root.backendConfig).length > 0) || (resolved.root.backendConfigFiles?.length ?? 0) > 0) {
|
|
1178
1342
|
return { wave: false, reason: "the root has backend config, which live-plan-set does not take" };
|
|
1179
1343
|
}
|
|
1180
1344
|
const root = choudoufuSetRootPath(resolved.projectRoot, resolved.dir);
|
|
@@ -1275,13 +1439,17 @@ export interface ChoudoufuPlanSetResult extends ChoudoufuPlanSet {
|
|
|
1275
1439
|
* `live-wave-apply` hands back to choudoufu with the set digest.
|
|
1276
1440
|
*/
|
|
1277
1441
|
export async function choudoufuPlanSet(args: TerraformRootArgs, signal?: AbortSignal): Promise<ChoudoufuPlanSetResult> {
|
|
1278
|
-
|
|
1442
|
+
return planSetIn(await resolveRoot(args, signal), args.root, signal);
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/** {@link choudoufuPlanSet} over a resolved root, `key` naming it in errors, in the waves directory and as the change-set member. */
|
|
1446
|
+
async function planSetIn(resolved: ResolvedRoot, key: string, signal?: AbortSignal): Promise<ChoudoufuPlanSetResult> {
|
|
1279
1447
|
const { binary, root, dir, projectRoot } = resolved;
|
|
1280
|
-
if (binary !== "choudoufu") throw new Error(`choudoufuPlanSet: root "${
|
|
1448
|
+
if (binary !== "choudoufu") throw new Error(`choudoufuPlanSet: root "${key}" runs ${binary}, not choudoufu`);
|
|
1281
1449
|
await ensureChoudoufuWavesVersion(binary, signal);
|
|
1282
1450
|
const rootPath = choudoufuSetRootPath(projectRoot, dir);
|
|
1283
|
-
if (rootPath === undefined) throw new Error(`choudoufuPlanSet: root "${
|
|
1284
|
-
const wavesDir = choudoufuWavesDir(projectRoot,
|
|
1451
|
+
if (rootPath === undefined) throw new Error(`choudoufuPlanSet: root "${key}" (${dir}) is not inside ${projectRoot}`);
|
|
1452
|
+
const wavesDir = choudoufuWavesDir(projectRoot, key);
|
|
1285
1453
|
mkdirSync(wavesDir, { recursive: true });
|
|
1286
1454
|
const cmd = choudoufuPlanSetCommand({ binary, root: rootPath, outDir: fromProject(projectRoot, join(wavesDir, "out")) });
|
|
1287
1455
|
|
|
@@ -1299,12 +1467,64 @@ export async function choudoufuPlanSet(args: TerraformRootArgs, signal?: AbortSi
|
|
|
1299
1467
|
stdout = failure.stdout ?? "";
|
|
1300
1468
|
}
|
|
1301
1469
|
|
|
1302
|
-
const parsed = parseChoudoufuPlanSet(stdout, { member:
|
|
1470
|
+
const parsed = parseChoudoufuPlanSet(stdout, { member: key, root: rootPath });
|
|
1303
1471
|
const planSetFile = join(wavesDir, "plan-set.json");
|
|
1304
1472
|
writeFileSync(planSetFile, stdout);
|
|
1305
1473
|
return { ...parsed, planSetFile, root: rootPath };
|
|
1306
1474
|
}
|
|
1307
1475
|
|
|
1476
|
+
// ── A choudoufu workspace member's outputs (#4455) ─────────────────────────
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
* A choudoufu member of the workspace, as `member-outputs` names it: not a
|
|
1480
|
+
* `terraform.roots` entry of the reading project but a directory the
|
|
1481
|
+
* workspace declaration gives. Its binary is `choudoufu`, it has no var
|
|
1482
|
+
* files, workspace or backend config, and it runs from `projectRoot`, a
|
|
1483
|
+
* directory above it (the workspace root), since `live-plan-set` plans only
|
|
1484
|
+
* roots inside the directory it runs in.
|
|
1485
|
+
*/
|
|
1486
|
+
export interface ChoudoufuMemberArgs {
|
|
1487
|
+
/** The member's name: the waves directory's name, and the plan's member in errors. */
|
|
1488
|
+
member: string;
|
|
1489
|
+
/** The member's directory, absolute. */
|
|
1490
|
+
dir: string;
|
|
1491
|
+
/** Where `live-plan-set` runs from, absolute: a directory above `dir`. */
|
|
1492
|
+
projectRoot: string;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
async function resolveMemberRoot(args: ChoudoufuMemberArgs, signal?: AbortSignal): Promise<ResolvedRoot> {
|
|
1496
|
+
const binary = "choudoufu";
|
|
1497
|
+
await ensureChoudoufuVersion(binary, signal);
|
|
1498
|
+
const dir = resolve(args.dir);
|
|
1499
|
+
const estate = detectLiveEstate(dir);
|
|
1500
|
+
return { binary, root: { dir }, dir, ...(estate !== undefined ? { estate } : {}), live: estate !== undefined, projectRoot: resolve(args.projectRoot) };
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
/**
|
|
1504
|
+
* The member's outputs as applied (#4455): `choudoufu init`, then `choudoufu
|
|
1505
|
+
* output -json` in its directory, the read the `terraform-apply` capability's
|
|
1506
|
+
* `outputs` makes for a root. A live estate's outputs come from its record
|
|
1507
|
+
* store.
|
|
1508
|
+
*/
|
|
1509
|
+
export async function choudoufuMemberOutputs(args: ChoudoufuMemberArgs, signal?: AbortSignal): Promise<Record<string, unknown>> {
|
|
1510
|
+
const resolved = await resolveMemberRoot(args, signal);
|
|
1511
|
+
const { stdout, stderr } = await run(terraformInitCommand({ binary: resolved.binary }), resolved.dir, terraformEnvironment(resolved.root), signal);
|
|
1512
|
+
report(stdout, stderr);
|
|
1513
|
+
return outputsIn(resolved, signal);
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
/**
|
|
1517
|
+
* The member planned as a one-root set (#4455), the way a choudoufu root in
|
|
1518
|
+
* a gated wave is ({@link choudoufuPlanSet}): `live-plan-set -json` from
|
|
1519
|
+
* `projectRoot`. The document's embedded plan carries `planned_values` and
|
|
1520
|
+
* `output_changes`, which say what the member's outputs will be.
|
|
1521
|
+
*/
|
|
1522
|
+
export async function choudoufuMemberPlanSet(args: ChoudoufuMemberArgs, signal?: AbortSignal): Promise<ChoudoufuPlanSetResult> {
|
|
1523
|
+
const resolved = await resolveMemberRoot(args, signal);
|
|
1524
|
+
if (!resolved.live) throw new Error(`choudoufu member "${args.member}" (${resolved.dir}) declares no live estate, so live-plan-set cannot plan it`);
|
|
1525
|
+
return planSetIn(resolved, args.member, signal);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1308
1528
|
/**
|
|
1309
1529
|
* What a choudoufu root keeps in the fan-out's attempt record (#3459):
|
|
1310
1530
|
* choudoufu's resume file, under the set digest it was written for.
|
|
@@ -1514,10 +1734,11 @@ export function terraformPlanReadCommand(opts: { binary: string; planFile: strin
|
|
|
1514
1734
|
* The one line a person runs to initialise a root chant refuses to plan,
|
|
1515
1735
|
* with the root's `backendConfig` carried, so it can be pasted as printed.
|
|
1516
1736
|
*/
|
|
1517
|
-
export function terraformInitLine(opts: { binary: string; dir: string; backendConfig?: Record<string, string
|
|
1737
|
+
export function terraformInitLine(opts: { binary: string; dir: string; backendConfig?: Record<string, string>; backendConfigFiles?: readonly string[] }): string {
|
|
1518
1738
|
const init = terraformInitCommand({
|
|
1519
1739
|
binary: opts.binary,
|
|
1520
1740
|
...(opts.backendConfig ? { backendConfig: opts.backendConfig } : {}),
|
|
1741
|
+
...(opts.backendConfigFiles ? { backendConfigFiles: opts.backendConfigFiles } : {}),
|
|
1521
1742
|
});
|
|
1522
1743
|
return init.replace(`${opts.binary} init`, `${opts.binary} -chdir=${quoteArg(opts.dir)} init`);
|
|
1523
1744
|
}
|
|
@@ -1629,7 +1850,12 @@ export async function terraformPlanRead(
|
|
|
1629
1850
|
): Promise<TerraformPlanReadResult> {
|
|
1630
1851
|
const { binary, root, dir } = await resolveRoot(args, signal);
|
|
1631
1852
|
const env = terraformEnvironment(root);
|
|
1632
|
-
const initLine = terraformInitLine({
|
|
1853
|
+
const initLine = terraformInitLine({
|
|
1854
|
+
binary,
|
|
1855
|
+
dir,
|
|
1856
|
+
...(root.backendConfig ? { backendConfig: root.backendConfig } : {}),
|
|
1857
|
+
...(root.backendConfigFiles ? { backendConfigFiles: root.backendConfigFiles } : {}),
|
|
1858
|
+
});
|
|
1633
1859
|
const notInitialised = (detail: string): TerraformPlanReadError =>
|
|
1634
1860
|
new TerraformPlanReadError(
|
|
1635
1861
|
"not-initialised",
|
|
@@ -1912,6 +2138,65 @@ export async function choudoufuLivePlan(
|
|
|
1912
2138
|
};
|
|
1913
2139
|
}
|
|
1914
2140
|
|
|
2141
|
+
/** What {@link choudoufuLiveGraph} resolved. */
|
|
2142
|
+
export type ChoudoufuLiveGraphResult =
|
|
2143
|
+
| {
|
|
2144
|
+
/** choudoufu printed the engine graph document. */
|
|
2145
|
+
supported: true;
|
|
2146
|
+
/** The document, parsed: a GraphIR v1 with `meta.engineGraph` (chant#4527's schema). */
|
|
2147
|
+
json: unknown;
|
|
2148
|
+
/** Absolute path of the root module directory. */
|
|
2149
|
+
dir: string;
|
|
2150
|
+
}
|
|
2151
|
+
| {
|
|
2152
|
+
/** This choudoufu has no `live-graph -from-plan` (older than {@link MIN_CHOUDOUFU_GRAPH_VERSION}). */
|
|
2153
|
+
supported: false;
|
|
2154
|
+
/** choudoufu's own first line, for the note. */
|
|
2155
|
+
detail: string;
|
|
2156
|
+
dir: string;
|
|
2157
|
+
};
|
|
2158
|
+
|
|
2159
|
+
export interface ChoudoufuLiveGraphArgs extends TerraformRootArgs {
|
|
2160
|
+
/** Absolute path of the `live-plan -json` document this graph takes its facts from. */
|
|
2161
|
+
fromPlan: string;
|
|
2162
|
+
/** The estate (`-estate`), for a root that does not declare its own. */
|
|
2163
|
+
estate?: string;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
/**
|
|
2167
|
+
* `choudoufu live-graph -json -from-plan=<file>` (choudoufu#2285, read by
|
|
2168
|
+
* chant#4528): the root's graph as one engine graph document, its facts taken
|
|
2169
|
+
* from a `live-plan -json` document this process already read. No second live
|
|
2170
|
+
* read: choudoufu builds the graph from the configuration and that file
|
|
2171
|
+
* alone, starts no provider and calls no cloud, so facts and verdicts come
|
|
2172
|
+
* from the same refresh (choudoufu #1014).
|
|
2173
|
+
*
|
|
2174
|
+
* A usage error ({@link classifyLiveGraphFailure}) resolves `supported:
|
|
2175
|
+
* false` rather than throwing, since the caller degrades to no facts; any
|
|
2176
|
+
* other failure throws with choudoufu's output. Warnings (an empty scope
|
|
2177
|
+
* estate, a plan without `observed_at`) go to stderr and are echoed like
|
|
2178
|
+
* every other activity's.
|
|
2179
|
+
*/
|
|
2180
|
+
export async function choudoufuLiveGraph(args: ChoudoufuLiveGraphArgs, signal?: AbortSignal): Promise<ChoudoufuLiveGraphResult> {
|
|
2181
|
+
const resolved = await resolveRoot(args, signal);
|
|
2182
|
+
const { binary, dir } = resolved;
|
|
2183
|
+
const env = terraformEnvironment(resolved.root);
|
|
2184
|
+
const estateFlag: { estate?: string } = resolved.estate === undefined && args.estate !== undefined ? { estate: args.estate } : {};
|
|
2185
|
+
const cmd = choudoufuLiveGraphCommand({ binary, fromPlan: args.fromPlan, ...estateFlag });
|
|
2186
|
+
try {
|
|
2187
|
+
const { stdout, stderr } = await run(cmd, dir, env, signal);
|
|
2188
|
+
if (stderr) console.error(stderr);
|
|
2189
|
+
return { supported: true, json: JSON.parse(liveDocumentFrom(stdout)), dir };
|
|
2190
|
+
} catch (err) {
|
|
2191
|
+
const failure = err as ExecFailure;
|
|
2192
|
+
if (typeof failure.code !== "number") throw err;
|
|
2193
|
+
const output = `${failure.stderr ?? ""}\n${failure.stdout ?? ""}`;
|
|
2194
|
+
const detail = output.trim().split("\n").find((line) => line.trim() !== "")?.trim() ?? `exit ${failure.code}`;
|
|
2195
|
+
if (classifyLiveGraphFailure(failure.code, output) === "unsupported") return { supported: false, detail, dir };
|
|
2196
|
+
throw new Error(`${binary} live-graph failed in ${dir} (exit ${failure.code})${detail ? `\n${output.trim()}` : ""}`);
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
|
|
1915
2200
|
/**
|
|
1916
2201
|
* `choudoufu live-ls -estate=<estate> -json [-consistent]`: every resource
|
|
1917
2202
|
* the account holds under the estate, read straight from the Resource Groups
|
|
@@ -66,7 +66,8 @@ export const terraformInitContract = activityContract(
|
|
|
66
66
|
upgrade: z.boolean().optional(),
|
|
67
67
|
reconfigure: z.boolean().optional(),
|
|
68
68
|
}),
|
|
69
|
-
|
|
69
|
+
// `rootPath` (#4482) is what TerraformApplyOp's Init step publishes as `TerraformRootPath`; OPS012 checks it here.
|
|
70
|
+
z.object({ dir: z.string(), workspace: z.string().optional(), rootPath: z.string().optional() }),
|
|
70
71
|
rootEntity,
|
|
71
72
|
);
|
|
72
73
|
|
|
@@ -181,6 +182,28 @@ export const choudoufuAdoptContract = activityContract(
|
|
|
181
182
|
rootEntity,
|
|
182
183
|
);
|
|
183
184
|
|
|
185
|
+
/**
|
|
186
|
+
* `choudoufuPlanSet` (#4483): one live choudoufu root planned as a one-root
|
|
187
|
+
* set. `changeSet` is the root's part, the field an Op hands to
|
|
188
|
+
* `composeChangeSet`; `planDigest` is what a gate binds; `planSetFile` and
|
|
189
|
+
* `setDigest` are what a later `live-wave-apply` takes.
|
|
190
|
+
*/
|
|
191
|
+
export const choudoufuPlanSetContract = activityContract(
|
|
192
|
+
"choudoufuPlanSet",
|
|
193
|
+
z.strictObject({ ...rootArgs }),
|
|
194
|
+
z.object({
|
|
195
|
+
setDigest: z.string(),
|
|
196
|
+
rootDigest: z.string(),
|
|
197
|
+
planDigest: z.string(),
|
|
198
|
+
changed: z.boolean(),
|
|
199
|
+
json: z.unknown(),
|
|
200
|
+
changeSet: z.object({ member: z.object({ member: z.string(), planDigest: z.string().nullable() }).passthrough(), entries: z.array(z.unknown()) }),
|
|
201
|
+
planSetFile: z.string(),
|
|
202
|
+
root: z.string(),
|
|
203
|
+
}),
|
|
204
|
+
rootEntity,
|
|
205
|
+
);
|
|
206
|
+
|
|
184
207
|
/** One root of a pin-bump rollout ({@link PinRoot} in `../pin/waves.ts`). */
|
|
185
208
|
const pinRoot = z.strictObject({ root: z.string(), dependsOn: z.array(z.string()).optional(), tsSource: z.string().optional() });
|
|
186
209
|
|
package/src/op/builders.ts
CHANGED
|
@@ -31,6 +31,7 @@ import type {
|
|
|
31
31
|
ChoudoufuLiveLsArgs,
|
|
32
32
|
ChoudoufuLiveCheckArgs,
|
|
33
33
|
ChoudoufuAdoptArgs,
|
|
34
|
+
TerraformRootArgs,
|
|
34
35
|
} from "./activities/terraform";
|
|
35
36
|
import type { TerraformPinRolloutArgs } from "./activities/pin-rollout";
|
|
36
37
|
|
|
@@ -186,6 +187,19 @@ export const terraformShow = (
|
|
|
186
187
|
);
|
|
187
188
|
};
|
|
188
189
|
|
|
190
|
+
/**
|
|
191
|
+
* `choudoufuPlanSet` (#4483): `live-plan-set -json` over one live choudoufu
|
|
192
|
+
* root. Hand `step.out.changeSet` from each root's step to `composeChangeSet`
|
|
193
|
+
* to make one change-set document over several roots, such as one per cloud.
|
|
194
|
+
*/
|
|
195
|
+
export const choudoufuPlanSet = (
|
|
196
|
+
root: string,
|
|
197
|
+
opts?: WithStepRefs<Omit<TerraformRootArgs, "root">> & StepOpts,
|
|
198
|
+
): NamedActivityStep => {
|
|
199
|
+
const { args, profile, id } = takeProfileAndId(opts as Record<string, unknown> | undefined);
|
|
200
|
+
return activity("choudoufuPlanSet", { root, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
201
|
+
};
|
|
202
|
+
|
|
189
203
|
/**
|
|
190
204
|
* One run of a pin-bump rollout (#3189). `opts` is
|
|
191
205
|
* {@link TerraformPinRolloutArgs} itself. It names no root: the rollout finds
|