@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,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Variables read from another root's state (#4545, Atmos reads moved from
|
|
3
|
+
* terragucci's `atmos.ts`): an Atmos stack that sets a var with
|
|
4
|
+
* `!terraform.state <component> [<stack>] <output>` plans on the upstream
|
|
5
|
+
* instance's output, which only the job that holds a credential can read.
|
|
6
|
+
*
|
|
7
|
+
* In the `terraform-apply` step a read is `{ var, root, output }`: the var it
|
|
8
|
+
* sets, the `terraform.roots` entry whose state holds the value (its
|
|
9
|
+
* directory and workspace come from that entry), and the output followed by
|
|
10
|
+
* the keys into its value (`.subnets.private` is `["subnets", "private"]`).
|
|
11
|
+
* The step reads each upstream's `output -json` once and passes the values
|
|
12
|
+
* as `-var`, under the step's own `vars`, which win. A read whose upstream
|
|
13
|
+
* has no state, or no such output yet, waits: the root is not planned on a
|
|
14
|
+
* stand-in, and the wave says which upstream to apply first.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** One var a root reads from another root's state. */
|
|
18
|
+
export interface TerraformStateRead {
|
|
19
|
+
/** The variable it sets. */
|
|
20
|
+
var: string;
|
|
21
|
+
/** The `terraform.roots` entry whose state holds the value. */
|
|
22
|
+
root: string;
|
|
23
|
+
/** The output, then the keys into its value. */
|
|
24
|
+
output: string[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** What filling a root's reads came to. */
|
|
28
|
+
export interface FilledStateReads {
|
|
29
|
+
/** The values, by var. Complete only when `waiting` and `errors` are empty. */
|
|
30
|
+
vars: Record<string, unknown>;
|
|
31
|
+
/** Reads whose upstream has no such value yet: the root waits for these upstreams to apply. */
|
|
32
|
+
waiting: Array<{ read: TerraformStateRead; why: string }>;
|
|
33
|
+
/** Upstreams whose state could not be read at all. */
|
|
34
|
+
errors: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** What is wrong with a step's `reads`, empty when nothing is. */
|
|
38
|
+
export function stateReadsProblems(reads: unknown): string[] {
|
|
39
|
+
if (reads === undefined) return [];
|
|
40
|
+
if (!Array.isArray(reads)) return ["reads must be a list of { var, root, output }"];
|
|
41
|
+
const problems: string[] = [];
|
|
42
|
+
const vars = new Set<string>();
|
|
43
|
+
for (const [i, r] of reads.entries()) {
|
|
44
|
+
const read = r as Partial<TerraformStateRead> | null;
|
|
45
|
+
if (!read || typeof read !== "object") {
|
|
46
|
+
problems.push(`reads[${i}] must be { var, root, output }`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (typeof read.var !== "string" || read.var === "") problems.push(`reads[${i}].var must name a variable`);
|
|
50
|
+
else if (vars.has(read.var)) problems.push(`reads[${i}] sets ${read.var}, which an earlier read sets too`);
|
|
51
|
+
else vars.add(read.var);
|
|
52
|
+
if (typeof read.root !== "string" || read.root === "") problems.push(`reads[${i}].root must name a terraform.roots entry`);
|
|
53
|
+
if (!Array.isArray(read.output) || read.output.length === 0 || !read.output.every((k) => typeof k === "string" && k !== "")) problems.push(`reads[${i}].output must be the output's name, then any keys into its value`);
|
|
54
|
+
}
|
|
55
|
+
return problems;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The value a read names in its upstream's outputs, or undefined when the outputs do not have it. */
|
|
59
|
+
export function readOutputValue(outputs: Record<string, unknown>, output: readonly string[]): { value: unknown } | undefined {
|
|
60
|
+
const [name, ...keys] = output;
|
|
61
|
+
if (name === undefined || !(name in outputs)) return undefined;
|
|
62
|
+
let v: unknown = outputs[name];
|
|
63
|
+
for (const k of keys) {
|
|
64
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || !(k in (v as Record<string, unknown>))) return undefined;
|
|
65
|
+
v = (v as Record<string, unknown>)[k];
|
|
66
|
+
}
|
|
67
|
+
return { value: v };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Fill `reads` from each upstream's outputs, read once per upstream through
|
|
72
|
+
* `outputsOf`, which throws when the state cannot be read.
|
|
73
|
+
*/
|
|
74
|
+
export async function fillStateReads(reads: readonly TerraformStateRead[], outputsOf: (root: string) => Promise<Record<string, unknown>>): Promise<FilledStateReads> {
|
|
75
|
+
const result: FilledStateReads = { vars: {}, waiting: [], errors: [] };
|
|
76
|
+
const cache = new Map<string, Promise<Record<string, unknown>>>();
|
|
77
|
+
for (const read of reads) {
|
|
78
|
+
if (!cache.has(read.root)) cache.set(read.root, outputsOf(read.root));
|
|
79
|
+
let outputs: Record<string, unknown>;
|
|
80
|
+
try {
|
|
81
|
+
outputs = await cache.get(read.root)!;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
result.errors.push(`it reads ${read.var} from ${read.root}, whose state could not be read: ${err instanceof Error ? err.message : String(err)}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const got = readOutputValue(outputs, read.output);
|
|
87
|
+
if (!got) {
|
|
88
|
+
result.waiting.push({ read, why: Object.keys(outputs).length === 0 ? "has no state yet" : `has no output ${read.output.join(".")} yet` });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
result.vars[read.var] = got.value;
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Why a root with waiting reads was not planned, naming what to apply first. */
|
|
97
|
+
export function waitingReadsReason(waiting: FilledStateReads["waiting"]): string {
|
|
98
|
+
const upstreams = [...new Set(waiting.map((w) => w.read.root))].sort();
|
|
99
|
+
return `not planned: ${waiting.map((w) => `it reads ${w.read.var} from ${w.read.root}, which ${w.why}`).join("; ")}; apply ${upstreams.join(", ")} first`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The reads an Atmos instance's edges file lists (`{ reads: [{ var,
|
|
104
|
+
* upstream, output }] }`, as terragucci's `atmos write` leaves beside each
|
|
105
|
+
* instance), with each upstream mapped to its `terraform.roots` entry by
|
|
106
|
+
* `rootOf` (by default the upstream's own path).
|
|
107
|
+
*/
|
|
108
|
+
export function atmosStateReads(edges: unknown, rootOf: (upstream: string) => string = (u) => u): TerraformStateRead[] {
|
|
109
|
+
const reads = (edges as { reads?: unknown } | null)?.reads;
|
|
110
|
+
if (!Array.isArray(reads)) return [];
|
|
111
|
+
return reads.flatMap((r) => {
|
|
112
|
+
const read = r as { var?: unknown; upstream?: unknown; output?: unknown } | null;
|
|
113
|
+
if (!read || typeof read.var !== "string" || typeof read.upstream !== "string" || !Array.isArray(read.output) || !read.output.every((k) => typeof k === "string")) return [];
|
|
114
|
+
return [{ var: read.var, root: rootOf(read.upstream), output: read.output as string[] }];
|
|
115
|
+
});
|
|
116
|
+
}
|
|
@@ -245,7 +245,8 @@ export function terragruntAffected(input: TerragruntAffectedInput): TerragruntAf
|
|
|
245
245
|
const moduleDirs = terragruntModuleDirs(unit);
|
|
246
246
|
const called = new Map<string, string>();
|
|
247
247
|
for (const m of moduleDirs) {
|
|
248
|
-
|
|
248
|
+
// Terragrunt runs tofu when it is installed, so a module's `.tofu` files count (chant#4457).
|
|
249
|
+
for (const d of rootWatchPaths(input.dir, { dir: m }, "tofu")) if (!moduleDirs.includes(d) && !called.has(d)) called.set(d, m);
|
|
249
250
|
}
|
|
250
251
|
const viaFile = new Map<string, string[]>();
|
|
251
252
|
const viaCall = new Map<string, string[]>();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sources a root uses (chant#3924): module calls and provider addresses
|
|
3
|
+
* down the local tree, implied providers, a Terragrunt unit's source, the
|
|
4
|
+
* normal forms, and the local calls that cannot be followed.
|
|
5
|
+
*/
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { describe, expect, test } from "vitest";
|
|
8
|
+
import { usedSources } from "./used-sources";
|
|
9
|
+
|
|
10
|
+
const FIX = join(import.meta.dirname, "__fixtures__", "used-sources");
|
|
11
|
+
const ROOT = join(FIX, "root");
|
|
12
|
+
|
|
13
|
+
describe("usedSources", () => {
|
|
14
|
+
test("lists the root's and its local modules' sources with their block paths", async () => {
|
|
15
|
+
const { used } = await usedSources(ROOT);
|
|
16
|
+
const rows = used.map((u) => [u.kind, u.block, u.source, u.normal]);
|
|
17
|
+
expect(rows).toEqual(
|
|
18
|
+
expect.arrayContaining([
|
|
19
|
+
["provider", "required_providers.aws", "hashicorp/aws", "registry.terraform.io/hashicorp/aws"],
|
|
20
|
+
["module", "module.vpc", "terraform-aws-modules/vpc/aws", "registry.terraform.io/terraform-aws-modules/vpc/aws"],
|
|
21
|
+
["module", "module.net", "./modules/net", "./modules/net"],
|
|
22
|
+
["provider", "provider.random", "hashicorp/random", "registry.terraform.io/hashicorp/random"],
|
|
23
|
+
["provider", "provider.google", "hashicorp/google", "registry.terraform.io/hashicorp/google"],
|
|
24
|
+
["module", "module.net > module.sg", "git::https://git.acme.dev/sg.git?ref=v1.0.0", "git::https://git.acme.dev/sg.git"],
|
|
25
|
+
["provider", "module.net > required_providers.thing", "Registry.Acme.dev/acme/thing", "registry.acme.dev/acme/thing"],
|
|
26
|
+
["provider", "module.net > provider.aws", "hashicorp/aws", "registry.terraform.io/hashicorp/aws"],
|
|
27
|
+
]),
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("names the file each source is written in, relative to the project", async () => {
|
|
32
|
+
const { used } = await usedSources(ROOT);
|
|
33
|
+
expect(used.find((u) => u.block === "module.net > module.sg")!.file).toBe("modules/net/main.tf");
|
|
34
|
+
expect(used.find((u) => u.block === "module.net > required_providers.thing")!.file).toBe("modules/net/versions.tf.json");
|
|
35
|
+
expect(used.find((u) => u.block === "provider.google")!.file).toBe("extra.tofu");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("says what implies a provider, and never implies the binary's own", async () => {
|
|
39
|
+
const { used } = await usedSources(ROOT);
|
|
40
|
+
expect(used.find((u) => u.block === "provider.random")!.implied).toBe('resource "random_id" "x"');
|
|
41
|
+
expect(used.find((u) => u.block === "module.net > provider.aws")!.implied).toBe('resource "aws_vpc" "v"');
|
|
42
|
+
expect(used.some((u) => u.block.endsWith("provider.terraform"))).toBe(false);
|
|
43
|
+
expect(used.some((u) => u.block === "provider.aws")).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("names local calls it cannot follow and stops at a cycle", async () => {
|
|
47
|
+
const { used, unread } = await usedSources(ROOT);
|
|
48
|
+
expect(unread.map((u) => [u.block, u.source])).toEqual([
|
|
49
|
+
["module.gone", "./modules/missing"],
|
|
50
|
+
["module.outside", "../../outside"],
|
|
51
|
+
]);
|
|
52
|
+
expect(unread[0]!.why).toContain("does not exist");
|
|
53
|
+
expect(unread[1]!.why).toContain("outside the project");
|
|
54
|
+
expect(used.filter((u) => u.block.startsWith("module.net > module.back > "))).toEqual([]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("reads only the root with followLocal off", async () => {
|
|
58
|
+
const { used, unread } = await usedSources(ROOT, { followLocal: false });
|
|
59
|
+
expect(used.some((u) => u.block.startsWith("module.net > "))).toBe(false);
|
|
60
|
+
expect(unread).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("leaves .tofu files out for terraform, and uses OpenTofu's registry for tofu", async () => {
|
|
64
|
+
const tf = await usedSources(ROOT, { binary: "terraform" });
|
|
65
|
+
expect(tf.used.some((u) => u.block === "provider.google")).toBe(false);
|
|
66
|
+
const tofu = await usedSources(ROOT, { binary: "tofu" });
|
|
67
|
+
expect(tofu.used.find((u) => u.block === "provider.google")!.normal).toBe("registry.opentofu.org/hashicorp/google");
|
|
68
|
+
expect(tofu.used.find((u) => u.block === "module.vpc")!.normal).toBe("registry.opentofu.org/terraform-aws-modules/vpc/aws");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("reads a Terragrunt unit's terraform source", async () => {
|
|
72
|
+
const { used } = await usedSources(join(FIX, "unit"), { project: FIX });
|
|
73
|
+
expect(used).toEqual([{ kind: "module", file: "unit/terragrunt.hcl", block: "terraform", source: "tfr:///acme/vpc/aws?version=1.0.0", normal: "registry.terraform.io/acme/vpc/aws" }]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every module source and provider address a root uses (chant#3924), read
|
|
3
|
+
* from its files before `init` downloads anything, so a product can check
|
|
4
|
+
* them against an allow list (terragucci's `sources:`) or a proxy map
|
|
5
|
+
* (chant#4606) in a check job.
|
|
6
|
+
*
|
|
7
|
+
* For a root and, with `followLocal`, each local module it calls (`./` and
|
|
8
|
+
* `../`, followed down to the modules they call), it reads each `module`
|
|
9
|
+
* block's `source`, each `required_providers` entry, and the providers a
|
|
10
|
+
* module uses with no entry: a `provider` block, or a resource, data or
|
|
11
|
+
* ephemeral block's `provider` argument or type prefix, which `init` installs
|
|
12
|
+
* as `hashicorp/<name>`. In the root itself it also reads a Terragrunt unit's
|
|
13
|
+
* `terraform { source }`. Files are `.tf`, `.tofu` and their `.json` forms;
|
|
14
|
+
* `binary` narrows them to the set that binary reads, with OpenTofu's rule
|
|
15
|
+
* that `x.tofu` hides `x.tf`.
|
|
16
|
+
*
|
|
17
|
+
* Each source carries its file and its block path from the root
|
|
18
|
+
* (`module.a > module.b > required_providers.x`) and its normal form
|
|
19
|
+
* (./registry/source-forms.ts). A local call that cannot be followed
|
|
20
|
+
* (outside the project, or missing) is named in `unread`, since what it
|
|
21
|
+
* uses cannot be read.
|
|
22
|
+
*/
|
|
23
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
24
|
+
import { join, posix, relative, sep } from "node:path";
|
|
25
|
+
import { loadHcl2json, type Hcl2Json } from "@intentius/chant/terraform/hcl2json";
|
|
26
|
+
import { isJsonConfigFile, jsonConfigTree, selectConfigFiles } from "./hcl/files";
|
|
27
|
+
import { impliedProvider, normalizeModuleSource, providerAddress, withoutQuery, type SourceBinary } from "./registry/source-forms";
|
|
28
|
+
import type { RegistryProxy } from "./registry/proxies";
|
|
29
|
+
|
|
30
|
+
/** One module source or provider address a root uses. */
|
|
31
|
+
export interface UsedSource {
|
|
32
|
+
kind: "module" | "provider";
|
|
33
|
+
/** The file it is written in, relative to the project, `/`-separated. */
|
|
34
|
+
file: string;
|
|
35
|
+
/**
|
|
36
|
+
* The block that names it, after the module calls that reach it:
|
|
37
|
+
* `module.vpc`, `terraform` for a terragrunt.hcl's source,
|
|
38
|
+
* `required_providers.aws`, or `provider.aws` for an implied one.
|
|
39
|
+
*/
|
|
40
|
+
block: string;
|
|
41
|
+
/** The source or address as written (`hashicorp/<name>` for an implied provider). */
|
|
42
|
+
source: string;
|
|
43
|
+
/**
|
|
44
|
+
* The normal form: for a module, the source without its query, normalised
|
|
45
|
+
* ({@link normalizeModuleSource}); for a provider, `<host>/<namespace>/<type>`
|
|
46
|
+
* ({@link providerAddress}), or the source as written when it is not an address.
|
|
47
|
+
*/
|
|
48
|
+
normal: string;
|
|
49
|
+
/** For an implied provider: the block that implies it. */
|
|
50
|
+
implied?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A local module call that could not be followed. */
|
|
54
|
+
export interface UnreadSource {
|
|
55
|
+
file: string;
|
|
56
|
+
block: string;
|
|
57
|
+
source: string;
|
|
58
|
+
why: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface UsedSourcesOptions {
|
|
62
|
+
/** Follow `./` and `../` module calls down the tree. Default true. */
|
|
63
|
+
followLocal?: boolean;
|
|
64
|
+
/** The project's top: file paths are relative to it, and a call that leaves it is not followed. Default the root's directory. */
|
|
65
|
+
project?: string;
|
|
66
|
+
/** Read only the files this binary reads, and default provider hosts to its registry. Default: every `.tf` and `.tofu` file, Terraform's registry. */
|
|
67
|
+
binary?: SourceBinary;
|
|
68
|
+
/** The HCL parser. Default: core's lazily loaded hcl2json. */
|
|
69
|
+
parser?: Hcl2Json;
|
|
70
|
+
/** Registry proxies (chant#4606): a source through one gets its upstream's normal form. */
|
|
71
|
+
proxies?: readonly RegistryProxy[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
type Tree = Record<string, unknown>;
|
|
75
|
+
|
|
76
|
+
/** A block list as hcl2json writes it (an array) or a JSON file may (one object). */
|
|
77
|
+
const bodies = (v: unknown): Tree[] => (Array.isArray(v) ? (v as Tree[]) : v && typeof v === "object" ? [v as Tree] : []);
|
|
78
|
+
|
|
79
|
+
const ALL_SUFFIXES = [".tf", ".tofu", ".tf.json", ".tofu.json"];
|
|
80
|
+
|
|
81
|
+
/** The configuration files of one module directory, plus terragrunt.hcl when `terragrunt`. */
|
|
82
|
+
function moduleFiles(dir: string, terragrunt: boolean, binary: SourceBinary | undefined): string[] {
|
|
83
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) return [];
|
|
84
|
+
const names = readdirSync(dir).filter((n) => {
|
|
85
|
+
try {
|
|
86
|
+
return statSync(join(dir, n)).isFile();
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const config = binary ? selectConfigFiles(names, binary) : names.filter((n) => ALL_SUFFIXES.some((s) => n.endsWith(s))).sort();
|
|
92
|
+
return terragrunt && names.includes("terragrunt.hcl") ? [...config, "terragrunt.hcl"] : config;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** The local name of the provider a resource, data or ephemeral block uses: its `provider` argument's, else its type's prefix. */
|
|
96
|
+
function providerOf(type: string, body: Tree): string {
|
|
97
|
+
const ref = typeof body.provider === "string" ? /^(?:\$\{)?([A-Za-z][A-Za-z0-9_-]*)/.exec(body.provider) : null;
|
|
98
|
+
return ref ? ref[1]! : type.split("_")[0]!;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const isLocal = (source: string): boolean => /^\.\.?\//.test(source);
|
|
102
|
+
|
|
103
|
+
interface DirRead {
|
|
104
|
+
providers: UsedSource[];
|
|
105
|
+
calls: { file: string; block: string; source: string }[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function readDir(abs: string, shown: string, prefix: string, top: boolean, o: Required<Pick<UsedSourcesOptions, "parser">> & UsedSourcesOptions): Promise<DirRead> {
|
|
109
|
+
const providers: UsedSource[] = [];
|
|
110
|
+
const calls: DirRead["calls"] = [];
|
|
111
|
+
const declared = new Set<string>();
|
|
112
|
+
const implied = new Map<string, { file: string; what: string }>();
|
|
113
|
+
const provider = (file: string, block: string, source: string, what?: string): UsedSource => ({
|
|
114
|
+
kind: "provider",
|
|
115
|
+
file,
|
|
116
|
+
block,
|
|
117
|
+
source,
|
|
118
|
+
normal: providerAddress(source, { binary: o.binary, proxies: o.proxies }) ?? source.trim().toLowerCase(),
|
|
119
|
+
...(what ? { implied: what } : {}),
|
|
120
|
+
});
|
|
121
|
+
for (const name of moduleFiles(abs, top, o.binary)) {
|
|
122
|
+
const file = shown === "." ? name : posix.join(shown, name);
|
|
123
|
+
const text = readFileSync(join(abs, name), "utf-8");
|
|
124
|
+
let tree: Tree;
|
|
125
|
+
try {
|
|
126
|
+
tree = (isJsonConfigFile(name) ? jsonConfigTree(text) : await o.parser.parse(file, text)) as Tree;
|
|
127
|
+
} catch (e) {
|
|
128
|
+
throw new Error(`${file} could not be read (${(e as Error).message.split("\n")[0]}), so its module and provider sources are unknown`);
|
|
129
|
+
}
|
|
130
|
+
if (name === "terragrunt.hcl") {
|
|
131
|
+
for (const b of bodies(tree.terraform)) if (typeof b.source === "string") calls.push({ file, block: `${prefix}terraform`, source: b.source });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
for (const [call, list] of Object.entries((tree.module as Tree | undefined) ?? {})) {
|
|
135
|
+
for (const b of bodies(list)) if (typeof b.source === "string") calls.push({ file, block: `${prefix}module.${call}`, source: b.source });
|
|
136
|
+
}
|
|
137
|
+
for (const t of bodies(tree.terraform)) {
|
|
138
|
+
for (const req of bodies(t.required_providers)) {
|
|
139
|
+
for (const [local, v] of Object.entries(req)) {
|
|
140
|
+
declared.add(local);
|
|
141
|
+
const source = v && typeof v === "object" && typeof (v as Tree).source === "string" ? ((v as Tree).source as string) : `hashicorp/${local}`;
|
|
142
|
+
providers.push(provider(file, `${prefix}required_providers.${local}`, source));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const local of Object.keys((tree.provider as Tree | undefined) ?? {})) if (!implied.has(local)) implied.set(local, { file, what: `provider "${local}"` });
|
|
147
|
+
for (const kind of ["resource", "data", "ephemeral"]) {
|
|
148
|
+
for (const [type, named] of Object.entries((tree[kind] as Tree | undefined) ?? {})) {
|
|
149
|
+
for (const [name, list] of Object.entries((named as Tree) ?? {})) {
|
|
150
|
+
for (const b of bodies(list)) {
|
|
151
|
+
const local = providerOf(type, b);
|
|
152
|
+
if (!implied.has(local)) implied.set(local, { file, what: `${kind} "${type}" "${name}"` });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const [local, at] of implied) {
|
|
159
|
+
const source = declared.has(local) ? undefined : impliedProvider(local);
|
|
160
|
+
if (source) providers.push(provider(at.file, `${prefix}provider.${local}`, source, at.what));
|
|
161
|
+
}
|
|
162
|
+
return { providers, calls };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Every module source and provider address the root at `dir` uses, and each
|
|
167
|
+
* local call that could not be followed. Throws, naming the file, when a
|
|
168
|
+
* file cannot be parsed, so a check fails loudly instead of checking less.
|
|
169
|
+
*/
|
|
170
|
+
export async function usedSources(dir: string, options: UsedSourcesOptions = {}): Promise<{ used: UsedSource[]; unread: UnreadSource[] }> {
|
|
171
|
+
const project = options.project ?? dir;
|
|
172
|
+
const o = { ...options, parser: options.parser ?? (await loadHcl2json()) };
|
|
173
|
+
const follow = options.followLocal !== false;
|
|
174
|
+
const used: UsedSource[] = [];
|
|
175
|
+
const unread: UnreadSource[] = [];
|
|
176
|
+
const shownOf = (abs: string) => relative(project, abs).split(sep).join("/") || ".";
|
|
177
|
+
|
|
178
|
+
const walk = async (rel: string, prefix: string, chain: string[], top: boolean): Promise<void> => {
|
|
179
|
+
const { providers, calls } = await readDir(join(project, rel), rel, prefix, top, o);
|
|
180
|
+
used.push(...providers);
|
|
181
|
+
for (const c of calls) {
|
|
182
|
+
used.push({ kind: "module", file: c.file, block: c.block, source: c.source, normal: isLocal(c.source) ? withoutQuery(c.source) : normalizeModuleSource(withoutQuery(c.source), { binary: o.binary, proxies: o.proxies }) });
|
|
183
|
+
if (!follow || !isLocal(c.source)) continue;
|
|
184
|
+
// A Terragrunt source's `//` marks the directory it copies; the module is the path with it read as one `/`.
|
|
185
|
+
const path = withoutQuery(c.source).replace(/\/\/+/g, "/");
|
|
186
|
+
const next = posix.normalize(posix.join(rel, path)).replace(/\/+$/, "") || ".";
|
|
187
|
+
if (next === ".." || next.startsWith("../")) {
|
|
188
|
+
unread.push({ file: c.file, block: c.block, source: c.source, why: "it is outside the project, so the sources it uses cannot be read" });
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (!existsSync(join(project, next))) {
|
|
192
|
+
unread.push({ file: c.file, block: c.block, source: c.source, why: `${next} does not exist, so the sources it uses cannot be read` });
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (chain.includes(next) || moduleFiles(join(project, next), false, o.binary).length === 0) continue;
|
|
196
|
+
await walk(next, `${c.block} > `, [...chain, next], false);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const start = shownOf(dir);
|
|
201
|
+
if (start === ".." || start.startsWith("../")) throw new Error(`${dir} is outside the project ${project}`);
|
|
202
|
+
await walk(start, "", [start], true);
|
|
203
|
+
return { used, unread };
|
|
204
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { join } from "node:path";
|
|
9
9
|
import { describe, expect, it } from "vitest";
|
|
10
10
|
import { describeWorkspaceKindConformance } from "@intentius/chant-test-utils";
|
|
11
|
-
import {
|
|
11
|
+
import { readPackageKinds } from "../../../packages/core/src/workspace/kinds";
|
|
12
12
|
|
|
13
13
|
const main = `terraform {\n required_version = ">= 1.5.0"\n}\n\nresource "null_resource" "x" {}\n`;
|
|
14
14
|
|
|
@@ -26,24 +26,11 @@ describeWorkspaceKindConformance({
|
|
|
26
26
|
{ name: "a root with the estate.chdf.hcl sidecar", kind: "choudoufu", files: { "main.tf": main, "estate.chdf.hcl": "" }, claims: true },
|
|
27
27
|
{ name: "a root with a live block", kind: "choudoufu", files: { "main.tf": main + '\nlive {\n name = "prod"\n}\n' }, claims: true },
|
|
28
28
|
{ name: "a stock root", kind: "choudoufu", files: { "main.tf": main }, claims: false },
|
|
29
|
-
// The pulumi kind (#3179) is a probe and a check of Pulumi.yaml.
|
|
30
|
-
{ name: "a Pulumi program", kind: "pulumi", files: { "Pulumi.yaml": "name: app\nruntime: nodejs\n", "index.ts": "" }, claims: true },
|
|
31
|
-
{ name: "a Pulumi program one level down", kind: "pulumi", files: { "infra/Pulumi.yaml": "name: app\nruntime: nodejs\n" }, claims: false },
|
|
32
|
-
{ name: "a stack file alone", kind: "pulumi", files: { "Pulumi.dev.yaml": "config: {}\n" }, claims: false },
|
|
33
29
|
],
|
|
34
30
|
});
|
|
35
31
|
|
|
36
|
-
describe("pulumi
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
it("names a schema that loads", () => {
|
|
40
|
-
expect(loadMemberFileSchema(memberFile, packageDir)).toBeUndefined();
|
|
41
|
-
});
|
|
42
|
-
it("passes a program with a runtime, named or in an object", () => {
|
|
43
|
-
expect(checkMemberFile(memberFile, "Pulumi.yaml", "name: app\nruntime: nodejs\n")).toEqual([]);
|
|
44
|
-
expect(checkMemberFile(memberFile, "Pulumi.yaml", "name: app\nruntime:\n name: python\n")).toEqual([]);
|
|
45
|
-
});
|
|
46
|
-
it("fails one with no runtime", () => {
|
|
47
|
-
expect(checkMemberFile(memberFile, "Pulumi.yaml", "name: app\n").length).toBeGreaterThan(0);
|
|
32
|
+
describe("the pulumi kind", () => {
|
|
33
|
+
it("is not here: it moved to the pulumi lexicon (#4453)", () => {
|
|
34
|
+
expect(readPackageKinds(join(import.meta.dirname, "..")).kinds.map((k) => k.name)).not.toContain("pulumi");
|
|
48
35
|
});
|
|
49
36
|
});
|
package/workspace-kinds.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "Member kinds this lexicon supplies to a chant workspace (#2545). chant reads this file as data and never imports the lexicon. Both probes are behold's, narrowed to the member's own directory: a choudoufu estate is a Terraform root with an estate.chdf.hcl sidecar or a live block, and the lexicon's choudoufu mode (#2103) reads it, so the kind lives here. Each kind's graph block is how chant workspace graph reads a member (#2874): a reader project with this lexicon and one root named for the member, with moduleRoot at the workspace root so a member's ../modules calls stay readable. The pulumi kind
|
|
2
|
+
"$comment": "Member kinds this lexicon supplies to a chant workspace (#2545). chant reads this file as data and never imports the lexicon. Both probes are behold's, narrowed to the member's own directory: a choudoufu estate is a Terraform root with an estate.chdf.hcl sidecar or a live block, and the lexicon's choudoufu mode (#2103) reads it, so the kind lives here. Each kind's graph block is how chant workspace graph reads a member (#2874): a reader project with this lexicon and one root named for the member, with moduleRoot at the workspace root so a member's ../modules calls stay readable. The pulumi kind moved to @intentius/chant-lexicon-pulumi (#4453).",
|
|
3
3
|
"schema": 1,
|
|
4
4
|
"kinds": [
|
|
5
5
|
{
|
|
@@ -52,29 +52,6 @@
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"name": "pulumi",
|
|
58
|
-
"description": "a Pulumi program, with a Pulumi.yaml in its directory",
|
|
59
|
-
"precedence": 310,
|
|
60
|
-
"probe": {
|
|
61
|
-
"anyFile": [
|
|
62
|
-
"Pulumi.yaml"
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
"memberFile": {
|
|
66
|
-
"path": "Pulumi.yaml",
|
|
67
|
-
"schema": "schemas/pulumi.schema.json"
|
|
68
|
-
},
|
|
69
|
-
"graph": {
|
|
70
|
-
"lexicon": "terraform",
|
|
71
|
-
"config": {
|
|
72
|
-
"pulumiMember": {
|
|
73
|
-
"dir": "{dir}",
|
|
74
|
-
"label": "{member}"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
55
|
}
|
|
79
56
|
]
|
|
80
57
|
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type Declarable } from "@intentius/chant/declarable";
|
|
2
|
-
/** The conventional place of the export, in the member's directory. */
|
|
3
|
-
export declare const PULUMI_EXPORT_FILE = "stack-export.json";
|
|
4
|
-
export interface PulumiMemberConfig {
|
|
5
|
-
/** The member's directory, absolute. */
|
|
6
|
-
dir: string;
|
|
7
|
-
/** Names the entities (`<label>/...`): the member's name. */
|
|
8
|
-
label?: string;
|
|
9
|
-
}
|
|
10
|
-
/** What the read found, carried on the graph's `meta.pulumiMember`. */
|
|
11
|
-
export interface PulumiMemberReport {
|
|
12
|
-
/** The export read, relative to the member's directory. */
|
|
13
|
-
export?: string;
|
|
14
|
-
objects: number;
|
|
15
|
-
/** False when the member has no readable export. */
|
|
16
|
-
exported: boolean;
|
|
17
|
-
/** Why nothing was read; set with `exported: false`. */
|
|
18
|
-
reason?: string;
|
|
19
|
-
}
|
|
20
|
-
export declare function readPulumiMember(opts: {
|
|
21
|
-
member: PulumiMemberConfig;
|
|
22
|
-
}): {
|
|
23
|
-
entities: Map<string, Declarable>;
|
|
24
|
-
warnings: string[];
|
|
25
|
-
report: PulumiMemberReport;
|
|
26
|
-
};
|
|
27
|
-
/** The report of the read in this process, left for `graphMeta` (see the aws member reader). */
|
|
28
|
-
export declare function setLastMemberReport(report: PulumiMemberReport | undefined): void;
|
|
29
|
-
export declare function lastMemberReport(): PulumiMemberReport | undefined;
|
|
30
|
-
//# sourceMappingURL=workspace-member.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-member.d.ts","sourceRoot":"","sources":["../src/workspace-member.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGjF,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,sBAAsB,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAAG;IACtE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;CAC5B,CAmDA;AAID,gGAAgG;AAChG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,IAAI,CAEhF;AAED,wBAAgB,gBAAgB,IAAI,kBAAkB,GAAG,SAAS,CAEjE"}
|
package/dist/workspace-member.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reading a pulumi workspace member into the graph (#3179).
|
|
3
|
-
*
|
|
4
|
-
* `chant workspace graph` writes a reader project for a member of kind
|
|
5
|
-
* `pulumi`, with `terraform.pulumiMember` in its config (see
|
|
6
|
-
* `workspace-kinds.json`). The plugin's `buildRoots` hook calls
|
|
7
|
-
* {@link readPulumiMember}, which reads the `pulumi stack export` JSON the
|
|
8
|
-
* member has checked in, at {@link PULUMI_EXPORT_FILE} in its directory. chant
|
|
9
|
-
* never runs the program and never calls `pulumi`: with no export there are no
|
|
10
|
-
* nodes, and `meta.pulumiMember` says `exported: false` and why.
|
|
11
|
-
*
|
|
12
|
-
* Nodes are the export's resources, keyed `<label>/<urn tail>`, where the tail
|
|
13
|
-
* is the URN after its stack and project (`aws:s3/bucket:Bucket::assets`).
|
|
14
|
-
* Provider resources (`pulumi:providers:*`) are left out; the resources that
|
|
15
|
-
* name them are not edged to them. Edges come from each resource's
|
|
16
|
-
* `dependencies` and `parent`, kept only when the target is a node. Inputs and
|
|
17
|
-
* outputs are not copied into the node, since an export can hold secrets.
|
|
18
|
-
*/
|
|
19
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
20
|
-
import { basename, join } from "node:path";
|
|
21
|
-
import { DECLARABLE_MARKER } from "@intentius/chant/declarable";
|
|
22
|
-
/** The conventional place of the export, in the member's directory. */
|
|
23
|
-
export const PULUMI_EXPORT_FILE = "stack-export.json";
|
|
24
|
-
const PROVIDER = /^pulumi:providers:/;
|
|
25
|
-
/** `urn:pulumi:<stack>::<project>::<tail>`: the tail, or the whole URN when it has another shape. */
|
|
26
|
-
function urnTail(urn) {
|
|
27
|
-
const parts = urn.split("::");
|
|
28
|
-
return urn.startsWith("urn:pulumi:") && parts.length >= 4 ? parts.slice(2).join("::") : urn;
|
|
29
|
-
}
|
|
30
|
-
export function readPulumiMember(opts) {
|
|
31
|
-
const { member } = opts;
|
|
32
|
-
const label = member.label ?? basename(member.dir);
|
|
33
|
-
const missing = (reason) => ({
|
|
34
|
-
entities: new Map(),
|
|
35
|
-
warnings: [`pulumi member "${label}" was not read: ${reason}`],
|
|
36
|
-
report: { objects: 0, exported: false, reason },
|
|
37
|
-
});
|
|
38
|
-
const file = join(member.dir, PULUMI_EXPORT_FILE);
|
|
39
|
-
if (!existsSync(file)) {
|
|
40
|
-
return missing(`no ${PULUMI_EXPORT_FILE} in the member; run \`pulumi stack export --file ${PULUMI_EXPORT_FILE}\` and check it in, and chant will read it (chant does not run the program)`);
|
|
41
|
-
}
|
|
42
|
-
let resources;
|
|
43
|
-
try {
|
|
44
|
-
const doc = JSON.parse(readFileSync(file, "utf-8"));
|
|
45
|
-
const list = doc?.deployment?.resources;
|
|
46
|
-
if (list !== undefined && !Array.isArray(list))
|
|
47
|
-
return missing(`${PULUMI_EXPORT_FILE} has a deployment.resources that is not a list`);
|
|
48
|
-
resources = (list ?? []);
|
|
49
|
-
}
|
|
50
|
-
catch (e) {
|
|
51
|
-
return missing(`${PULUMI_EXPORT_FILE} is not readable JSON: ${e.message}`);
|
|
52
|
-
}
|
|
53
|
-
const keyOf = new Map();
|
|
54
|
-
for (const r of resources) {
|
|
55
|
-
if (typeof r?.urn !== "string" || typeof r.type !== "string" || PROVIDER.test(r.type))
|
|
56
|
-
continue;
|
|
57
|
-
keyOf.set(r.urn, `${label}/${urnTail(r.urn)}`);
|
|
58
|
-
}
|
|
59
|
-
const entities = new Map();
|
|
60
|
-
for (const r of resources) {
|
|
61
|
-
const key = typeof r?.urn === "string" ? keyOf.get(r.urn) : undefined;
|
|
62
|
-
if (!key)
|
|
63
|
-
continue;
|
|
64
|
-
const references = new Map();
|
|
65
|
-
const add = (urn, via) => {
|
|
66
|
-
const to = typeof urn === "string" ? keyOf.get(urn) : undefined;
|
|
67
|
-
if (to && to !== key)
|
|
68
|
-
references.set(`${to}|${via}`, { to, viaAttr: via });
|
|
69
|
-
};
|
|
70
|
-
add(r.parent, "parent");
|
|
71
|
-
for (const d of Array.isArray(r.dependencies) ? r.dependencies : [])
|
|
72
|
-
add(d, "dependencies");
|
|
73
|
-
entities.set(key, {
|
|
74
|
-
lexicon: "terraform",
|
|
75
|
-
entityType: r.type,
|
|
76
|
-
kind: "resource",
|
|
77
|
-
props: {},
|
|
78
|
-
references: [...references.values()],
|
|
79
|
-
[DECLARABLE_MARKER]: true,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return { entities, warnings: [], report: { export: PULUMI_EXPORT_FILE, objects: entities.size, exported: true } };
|
|
83
|
-
}
|
|
84
|
-
let lastReport;
|
|
85
|
-
/** The report of the read in this process, left for `graphMeta` (see the aws member reader). */
|
|
86
|
-
export function setLastMemberReport(report) {
|
|
87
|
-
lastReport = report;
|
|
88
|
-
}
|
|
89
|
-
export function lastMemberReport() {
|
|
90
|
-
return lastReport;
|
|
91
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"title": "Pulumi.yaml",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"required": [
|
|
6
|
-
"name",
|
|
7
|
-
"runtime"
|
|
8
|
-
],
|
|
9
|
-
"properties": {
|
|
10
|
-
"name": {
|
|
11
|
-
"type": "string",
|
|
12
|
-
"minLength": 1
|
|
13
|
-
},
|
|
14
|
-
"runtime": {
|
|
15
|
-
"anyOf": [
|
|
16
|
-
{
|
|
17
|
-
"type": "string",
|
|
18
|
-
"minLength": 1
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"type": "object",
|
|
22
|
-
"required": [
|
|
23
|
-
"name"
|
|
24
|
-
],
|
|
25
|
-
"properties": {
|
|
26
|
-
"name": {
|
|
27
|
-
"type": "string"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|