@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,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An in-memory stand-in for HCP Terraform's private module registry
|
|
3
|
+
* (chant#4604), for the HCP module target's tests. It is a fetch function:
|
|
4
|
+
* nothing listens on a port and nothing leaves the process, and no HCP
|
|
5
|
+
* account or call is involved.
|
|
6
|
+
*
|
|
7
|
+
* It answers the calls the API docs give
|
|
8
|
+
* (developer.hashicorp.com/terraform/cloud-docs/api-docs/private-registry/modules):
|
|
9
|
+
*
|
|
10
|
+
* GET /api/v2/organizations/:org/registry-modules/private/:org/:name/:provider attributes.version-statuses
|
|
11
|
+
* POST /api/v2/organizations/:org/registry-modules 201, 422 when it exists
|
|
12
|
+
* POST /api/v2/organizations/:org/registry-modules/private/:org/:name/:provider/versions 201 with links.upload, 422 when it exists
|
|
13
|
+
* PUT https://archivist.terraform.io/v1/object/<id> the gzip tarball
|
|
14
|
+
*
|
|
15
|
+
* and the registry protocol Terraform installs through:
|
|
16
|
+
*
|
|
17
|
+
* GET /.well-known/terraform.json {"modules.v1": "/api/registry/v1/modules/"}
|
|
18
|
+
* GET /api/registry/v1/modules/:org/:name/:provider/:version/download 204, X-Terraform-Get
|
|
19
|
+
* GET https://archivist.terraform.io/v1/object/<id> the tarball
|
|
20
|
+
*
|
|
21
|
+
* A token the fake does not know gets 401. A known token without Manage
|
|
22
|
+
* modules, or any token when the organization has no entitlement, gets 404
|
|
23
|
+
* from the registry calls, as HCP answers. A version is `pending` once
|
|
24
|
+
* created, and turns `ok` after its tarball is uploaded and the module has
|
|
25
|
+
* been read `parseAfterReads` more times. `throttle(n)` answers the next n
|
|
26
|
+
* requests with 429. Every request is kept, headers and body included.
|
|
27
|
+
*/
|
|
28
|
+
import { gunzipSync } from "node:zlib";
|
|
29
|
+
export const ARCHIVIST = "archivist.terraform.io";
|
|
30
|
+
function headersOf(h) {
|
|
31
|
+
const out = {};
|
|
32
|
+
if (!h)
|
|
33
|
+
return out;
|
|
34
|
+
if (typeof h.forEach === "function" && typeof h.get === "function") {
|
|
35
|
+
h.forEach((v, k) => (out[k.toLowerCase()] = v));
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
for (const [k, v] of Object.entries(h))
|
|
39
|
+
out[k.toLowerCase()] = String(v);
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
function bodyOf(b) {
|
|
43
|
+
if (b === undefined || b === null)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (typeof b === "string")
|
|
46
|
+
return new TextEncoder().encode(b);
|
|
47
|
+
if (b instanceof Uint8Array)
|
|
48
|
+
return b;
|
|
49
|
+
if (b instanceof ArrayBuffer)
|
|
50
|
+
return new Uint8Array(b);
|
|
51
|
+
throw new Error("the fake takes a string or bytes as a body");
|
|
52
|
+
}
|
|
53
|
+
const doc = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/vnd.api+json" } });
|
|
54
|
+
const errors = (status, title) => doc(status, { errors: [{ status: String(status), title }] });
|
|
55
|
+
export function createFakeHcp(o) {
|
|
56
|
+
const host = o.host ?? "app.terraform.io";
|
|
57
|
+
const org = o.organization;
|
|
58
|
+
const requests = [];
|
|
59
|
+
const modules = new Map();
|
|
60
|
+
const objects = new Map();
|
|
61
|
+
let throttled = 0;
|
|
62
|
+
let throttleAfter;
|
|
63
|
+
let next = 0;
|
|
64
|
+
const newVersion = (module, version, status, commitSha, archive) => {
|
|
65
|
+
const object = `obj${++next}`;
|
|
66
|
+
objects.set(object, { module, version });
|
|
67
|
+
return { status, commitSha, object, readsLeft: o.parseAfterReads ?? 0, ...(archive ? { archive } : {}) };
|
|
68
|
+
};
|
|
69
|
+
const seed = (name, provider, version) => {
|
|
70
|
+
const key = `${name}/${provider}`;
|
|
71
|
+
const vs = modules.get(key) ?? new Map();
|
|
72
|
+
modules.set(key, vs);
|
|
73
|
+
if (version)
|
|
74
|
+
vs.set(version.version, newVersion(key, version.version, version.status ?? "ok", null, version.archive));
|
|
75
|
+
};
|
|
76
|
+
const moduleDoc = (name, provider, vs) => doc(200, {
|
|
77
|
+
data: {
|
|
78
|
+
id: `mod-${name}-${provider}`,
|
|
79
|
+
type: "registry-modules",
|
|
80
|
+
attributes: {
|
|
81
|
+
name,
|
|
82
|
+
provider,
|
|
83
|
+
namespace: org,
|
|
84
|
+
"registry-name": "private",
|
|
85
|
+
status: vs.size ? "setup_complete" : "pending",
|
|
86
|
+
"version-statuses": [...vs.entries()].map(([version, v]) => ({ version, status: v.status })),
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
const fetch = async (url, init = {}) => {
|
|
91
|
+
const method = (init.method ?? "GET").toUpperCase();
|
|
92
|
+
const headers = headersOf(init.headers);
|
|
93
|
+
const body = bodyOf(init.body);
|
|
94
|
+
requests.push({ method, url, headers, ...(body ? { body } : {}) });
|
|
95
|
+
if (throttled > 0) {
|
|
96
|
+
throttled--;
|
|
97
|
+
return new Response(JSON.stringify({ errors: [{ status: "429", title: "Too Many Requests" }] }), { status: 429, headers: throttleAfter !== undefined ? { "retry-after": throttleAfter } : {} });
|
|
98
|
+
}
|
|
99
|
+
const u = new URL(url);
|
|
100
|
+
if (u.host === ARCHIVIST) {
|
|
101
|
+
const id = /^\/v1\/object\/([^/]+)$/.exec(u.pathname)?.[1];
|
|
102
|
+
const ref = id ? objects.get(id) : undefined;
|
|
103
|
+
if (!ref)
|
|
104
|
+
return errors(404, "not found");
|
|
105
|
+
const v = modules.get(ref.module).get(ref.version);
|
|
106
|
+
if (method === "PUT") {
|
|
107
|
+
if (headers["content-type"] !== "application/octet-stream")
|
|
108
|
+
return errors(400, "content type");
|
|
109
|
+
if (!body)
|
|
110
|
+
return errors(400, "no body");
|
|
111
|
+
try {
|
|
112
|
+
gunzipSync(body);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
v.status = "reg_ingress_failed";
|
|
116
|
+
return new Response(null, { status: 200 });
|
|
117
|
+
}
|
|
118
|
+
v.archive = body;
|
|
119
|
+
if (v.readsLeft <= 0)
|
|
120
|
+
v.status = "ok";
|
|
121
|
+
return new Response(null, { status: 200 });
|
|
122
|
+
}
|
|
123
|
+
if (method === "GET")
|
|
124
|
+
return v.archive ? new Response(new Uint8Array(v.archive), { status: 200 }) : errors(404, "not found");
|
|
125
|
+
return errors(405, "method");
|
|
126
|
+
}
|
|
127
|
+
if (u.host !== host)
|
|
128
|
+
throw new TypeError(`fetch failed: the fake answers only ${host} and ${ARCHIVIST}, not ${u.host}`);
|
|
129
|
+
if (method === "GET" && u.pathname === "/.well-known/terraform.json")
|
|
130
|
+
return new Response(JSON.stringify({ "modules.v1": "/api/registry/v1/modules/" }), { status: 200 });
|
|
131
|
+
const bearer = /^Bearer (.+)$/i.exec(headers.authorization ?? "")?.[1];
|
|
132
|
+
if (!bearer || !o.tokens[bearer])
|
|
133
|
+
return errors(401, "unauthorized");
|
|
134
|
+
const allowed = o.tokens[bearer].manageModules && o.entitled !== false;
|
|
135
|
+
const proto = /^\/api\/registry\/v1\/modules\/([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)\/download$/.exec(u.pathname);
|
|
136
|
+
if (proto && method === "GET") {
|
|
137
|
+
if (proto[1] !== org || o.entitled === false)
|
|
138
|
+
return errors(404, "not found");
|
|
139
|
+
const v = modules.get(`${proto[2]}/${proto[3]}`)?.get(proto[4]);
|
|
140
|
+
if (!v || v.status !== "ok")
|
|
141
|
+
return errors(404, "not found");
|
|
142
|
+
return new Response(null, { status: 204, headers: { "X-Terraform-Get": `https://${ARCHIVIST}/v1/object/${v.object}` } });
|
|
143
|
+
}
|
|
144
|
+
const base = `/api/v2/organizations/${org}/registry-modules`;
|
|
145
|
+
if (!u.pathname.startsWith(base))
|
|
146
|
+
return errors(404, "not found");
|
|
147
|
+
if (!allowed)
|
|
148
|
+
return errors(404, "not found");
|
|
149
|
+
if (method === "POST" && u.pathname === base) {
|
|
150
|
+
const d = JSON.parse(new TextDecoder().decode(body ?? new Uint8Array()));
|
|
151
|
+
const a = d.data?.attributes ?? {};
|
|
152
|
+
if (d.data?.type !== "registry-modules" || typeof a.name !== "string" || typeof a.provider !== "string" || a["registry-name"] !== "private")
|
|
153
|
+
return errors(422, "malformed");
|
|
154
|
+
const key = `${a.name}/${a.provider}`;
|
|
155
|
+
if (modules.has(key))
|
|
156
|
+
return errors(422, "Name has already been taken");
|
|
157
|
+
modules.set(key, new Map());
|
|
158
|
+
return doc(201, { data: { type: "registry-modules", attributes: { name: a.name, provider: a.provider } } });
|
|
159
|
+
}
|
|
160
|
+
const m = /^\/private\/([^/]+)\/([^/]+)\/([^/]+)(\/versions)?$/.exec(u.pathname.slice(base.length));
|
|
161
|
+
if (!m || m[1] !== org)
|
|
162
|
+
return errors(404, "not found");
|
|
163
|
+
const key = `${m[2]}/${m[3]}`;
|
|
164
|
+
const vs = modules.get(key);
|
|
165
|
+
if (!vs)
|
|
166
|
+
return errors(404, "not found");
|
|
167
|
+
if (!m[4] && method === "GET") {
|
|
168
|
+
for (const v of vs.values()) {
|
|
169
|
+
if (v.status === "pending" && v.archive) {
|
|
170
|
+
if (v.readsLeft <= 0)
|
|
171
|
+
v.status = "ok";
|
|
172
|
+
else
|
|
173
|
+
v.readsLeft--;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return moduleDoc(m[2], m[3], vs);
|
|
177
|
+
}
|
|
178
|
+
if (m[4] && method === "POST") {
|
|
179
|
+
const d = JSON.parse(new TextDecoder().decode(body ?? new Uint8Array()));
|
|
180
|
+
const version = d.data?.attributes?.version;
|
|
181
|
+
if (d.data?.type !== "registry-module-versions" || typeof version !== "string")
|
|
182
|
+
return errors(422, "malformed");
|
|
183
|
+
if (vs.has(version))
|
|
184
|
+
return errors(422, "Version has already been taken");
|
|
185
|
+
const sha = d.data.attributes?.["commit-sha"];
|
|
186
|
+
const v = newVersion(key, version, "pending", typeof sha === "string" ? sha : null);
|
|
187
|
+
vs.set(version, v);
|
|
188
|
+
return doc(201, { data: { type: "registry-module-versions", attributes: { version, status: "pending", source: "tfe-api", "commit-sha": v.commitSha }, links: { upload: `https://${ARCHIVIST}/v1/object/${v.object}` } } });
|
|
189
|
+
}
|
|
190
|
+
return errors(405, "method");
|
|
191
|
+
};
|
|
192
|
+
return {
|
|
193
|
+
fetch,
|
|
194
|
+
requests,
|
|
195
|
+
modules,
|
|
196
|
+
seed,
|
|
197
|
+
throttle(n, retryAfter) {
|
|
198
|
+
throttled = n;
|
|
199
|
+
throttleAfter = retryAfter;
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** One request a fake was sent. */
|
|
2
|
+
export interface FakeRequest {
|
|
3
|
+
method: string;
|
|
4
|
+
url: string;
|
|
5
|
+
/** Header names lower-cased. */
|
|
6
|
+
headers: Record<string, string>;
|
|
7
|
+
body?: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
/** The fetch a fake answers: both the target's `fetch` and the reader's `registryFetch`. */
|
|
10
|
+
export type FakeFetch = (url: string, init?: {
|
|
11
|
+
method?: string;
|
|
12
|
+
headers?: unknown;
|
|
13
|
+
body?: unknown;
|
|
14
|
+
}) => Promise<Response>;
|
|
15
|
+
export declare function headersOf(h: unknown): Record<string, string>;
|
|
16
|
+
export declare function bodyOf(b: unknown): Uint8Array | undefined;
|
|
17
|
+
export declare const jsonAnswer: (status: number, doc: unknown) => Response;
|
|
18
|
+
/** The user and password of a `Basic` header, or undefined. */
|
|
19
|
+
export declare function basicOf(authorization: string | undefined): {
|
|
20
|
+
user: string;
|
|
21
|
+
password: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
/** The token of a `Bearer` header, or undefined. */
|
|
24
|
+
export declare const bearerOf: (authorization: string | undefined) => string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* A module tarball as the bucket registry serves one: a gzip of a ustar
|
|
27
|
+
* archive with the given files at its root (paths under 100 bytes), each
|
|
28
|
+
* directory written before its files.
|
|
29
|
+
*/
|
|
30
|
+
export declare function moduleTarball(files: Record<string, string | Uint8Array>, mtime?: number): Buffer;
|
|
31
|
+
//# sourceMappingURL=fake-http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-http.d.ts","sourceRoot":"","sources":["../../../src/registry/targets/fake-http.ts"],"names":[],"mappings":"AAQA,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,4FAA4F;AAC5F,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE1H,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS5D;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAMzD;AAED,eAAO,MAAM,UAAU,WAAY,MAAM,OAAO,OAAO,KAAG,QAA0G,CAAC;AAErK,+DAA+D;AAC/D,wBAAgB,OAAO,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAMzG;AAED,oDAAoD;AACpD,eAAO,MAAM,QAAQ,kBAAmB,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAA4D,CAAC;AAuBnI;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC,EAAE,KAAK,SAAgB,GAAG,MAAM,CAiBvG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pieces the in-memory host fakes share (chant#4605): reading a request's
|
|
3
|
+
* headers and body as a fetch caller passes them, JSON answers, basic and
|
|
4
|
+
* bearer header parsing, and a module tarball builder, so a test (in chant
|
|
5
|
+
* or in terragucci#1302) can make a real attested archive to publish.
|
|
6
|
+
*/
|
|
7
|
+
import { gzipSync } from "node:zlib";
|
|
8
|
+
export function headersOf(h) {
|
|
9
|
+
const out = {};
|
|
10
|
+
if (!h)
|
|
11
|
+
return out;
|
|
12
|
+
if (typeof h.forEach === "function" && typeof h.get === "function") {
|
|
13
|
+
h.forEach((v, k) => (out[k.toLowerCase()] = v));
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
for (const [k, v] of Object.entries(h))
|
|
17
|
+
out[k.toLowerCase()] = String(v);
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
export function bodyOf(b) {
|
|
21
|
+
if (b === undefined || b === null)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof b === "string")
|
|
24
|
+
return new TextEncoder().encode(b);
|
|
25
|
+
if (b instanceof Uint8Array)
|
|
26
|
+
return b;
|
|
27
|
+
if (b instanceof ArrayBuffer)
|
|
28
|
+
return new Uint8Array(b);
|
|
29
|
+
throw new Error("the fake takes a string or bytes as a body");
|
|
30
|
+
}
|
|
31
|
+
export const jsonAnswer = (status, doc) => new Response(JSON.stringify(doc), { status, headers: { "content-type": "application/json" } });
|
|
32
|
+
/** The user and password of a `Basic` header, or undefined. */
|
|
33
|
+
export function basicOf(authorization) {
|
|
34
|
+
const m = /^Basic (.+)$/i.exec(authorization ?? "");
|
|
35
|
+
if (!m)
|
|
36
|
+
return undefined;
|
|
37
|
+
const text = Buffer.from(m[1], "base64").toString("utf-8");
|
|
38
|
+
const at = text.indexOf(":");
|
|
39
|
+
return at < 0 ? undefined : { user: text.slice(0, at), password: text.slice(at + 1) };
|
|
40
|
+
}
|
|
41
|
+
/** The token of a `Bearer` header, or undefined. */
|
|
42
|
+
export const bearerOf = (authorization) => /^Bearer (.+)$/i.exec(authorization ?? "")?.[1];
|
|
43
|
+
/** A ustar header block for one entry. */
|
|
44
|
+
function tarHeader(path, size, type, mode, mtime) {
|
|
45
|
+
const h = Buffer.alloc(512);
|
|
46
|
+
const put = (text, at, len) => h.write(text.slice(0, len), at, len, "utf-8");
|
|
47
|
+
const oct = (n, len) => n.toString(8).padStart(len - 1, "0") + "\0";
|
|
48
|
+
put(path, 0, 100);
|
|
49
|
+
put(oct(mode, 8), 100, 8);
|
|
50
|
+
put(oct(0, 8), 108, 8);
|
|
51
|
+
put(oct(0, 8), 116, 8);
|
|
52
|
+
put(oct(size, 12), 124, 12);
|
|
53
|
+
put(oct(mtime, 12), 136, 12);
|
|
54
|
+
h.fill(0x20, 148, 156);
|
|
55
|
+
h.write(type, 156, 1, "latin1");
|
|
56
|
+
put("ustar\0", 257, 6);
|
|
57
|
+
put("00", 263, 2);
|
|
58
|
+
let sum = 0;
|
|
59
|
+
for (const b of h)
|
|
60
|
+
sum += b;
|
|
61
|
+
put(sum.toString(8).padStart(6, "0") + "\0 ", 148, 8);
|
|
62
|
+
return h;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A module tarball as the bucket registry serves one: a gzip of a ustar
|
|
66
|
+
* archive with the given files at its root (paths under 100 bytes), each
|
|
67
|
+
* directory written before its files.
|
|
68
|
+
*/
|
|
69
|
+
export function moduleTarball(files, mtime = 1700000000) {
|
|
70
|
+
const blocks = [];
|
|
71
|
+
const dirs = new Set();
|
|
72
|
+
for (const path of Object.keys(files).sort()) {
|
|
73
|
+
const parts = path.split("/");
|
|
74
|
+
for (let i = 1; i < parts.length; i++) {
|
|
75
|
+
const dir = parts.slice(0, i).join("/");
|
|
76
|
+
if (dirs.has(dir))
|
|
77
|
+
continue;
|
|
78
|
+
dirs.add(dir);
|
|
79
|
+
blocks.push(tarHeader(`${dir}/`, 0, "5", 0o755, mtime));
|
|
80
|
+
}
|
|
81
|
+
const raw = files[path];
|
|
82
|
+
const data = typeof raw === "string" ? Buffer.from(raw, "utf-8") : Buffer.from(raw);
|
|
83
|
+
blocks.push(tarHeader(path, data.length, "0", 0o644, mtime), data, Buffer.alloc((512 - (data.length % 512)) % 512));
|
|
84
|
+
}
|
|
85
|
+
blocks.push(Buffer.alloc(1024));
|
|
86
|
+
return gzipSync(Buffer.concat(blocks));
|
|
87
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type FakeFetch, type FakeRequest } from "./fake-http.js";
|
|
2
|
+
export interface FakeNexusOptions {
|
|
3
|
+
/** The host, such as `nexus.example.com`. */
|
|
4
|
+
host: string;
|
|
5
|
+
/** The hosted Terraform repositories' names. */
|
|
6
|
+
repos: string[];
|
|
7
|
+
/** Users (or user token name codes) and their passwords (or pass codes). */
|
|
8
|
+
users: Record<string, string>;
|
|
9
|
+
/** Whether the 3.95 token call is there. Default true. */
|
|
10
|
+
bearer?: boolean;
|
|
11
|
+
/** Whether an upload over a held version is taken. Default false: 400. */
|
|
12
|
+
redeploy?: boolean;
|
|
13
|
+
/** How many versions reads a new version answers 404 for. Default 0. */
|
|
14
|
+
cacheNotFound?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface FakeNexus {
|
|
17
|
+
fetch: FakeFetch;
|
|
18
|
+
requests: FakeRequest[];
|
|
19
|
+
/** Uploaded assets, keyed `<repo>/<ns>/<name>/<system>/<version>/<file>`. */
|
|
20
|
+
assets: Map<string, Uint8Array>;
|
|
21
|
+
/** Bearer tokens the token call issued. */
|
|
22
|
+
issued: Set<string>;
|
|
23
|
+
/** Put an asset in directly, as an upload by hand would. */
|
|
24
|
+
seed(repo: string, ns: string, name: string, system: string, version: string, file: string, bytes: Uint8Array): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createFakeNexus(o: FakeNexusOptions): FakeNexus;
|
|
27
|
+
//# sourceMappingURL=fake-nexus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-nexus.d.ts","sourceRoot":"","sources":["../../../src/registry/targets/fake-nexus.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAoD,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjH,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,6EAA6E;IAC7E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAChC,2CAA2C;IAC3C,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,4DAA4D;IAC5D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CACtH;AAQD,wBAAgB,eAAe,CAAC,CAAC,EAAE,gBAAgB,GAAG,SAAS,CA0F9D"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An in-memory stand-in for a Sonatype Nexus Repository hosted Terraform
|
|
3
|
+
* repository (chant#4605), for the Nexus module target's tests here and in
|
|
4
|
+
* terragucci#1302. It is a fetch function: nothing listens on a port and
|
|
5
|
+
* nothing leaves the process.
|
|
6
|
+
*
|
|
7
|
+
* It answers the calls terragucci#1299's research found in Sonatype's docs,
|
|
8
|
+
* under `/repository/<repo>/`:
|
|
9
|
+
*
|
|
10
|
+
* PUT v1/modules/<ns>/<name>/<system>/<version>/<file> basic credentials, the archive as the body
|
|
11
|
+
* GET v1/modules/<ns>/<name>/<system>/<version>/<file>
|
|
12
|
+
* GET v1/modules/<ns>/<name>/<system>/versions
|
|
13
|
+
* GET v1/modules/<ns>/<name>/<system>/<version>/download 204, X-Terraform-Get
|
|
14
|
+
* GET v1/api/token the 3.95 bearer token, for basic credentials
|
|
15
|
+
*
|
|
16
|
+
* There is no `/.well-known/terraform.json`: a Nexus repository is reached
|
|
17
|
+
* through a CLI `host` block. Without credentials every call gets 401.
|
|
18
|
+
* `bearer: false` drops the token call (Nexus before 3.95), and reads then
|
|
19
|
+
* take basic credentials only. A body that is not a zip or a gzip holding a
|
|
20
|
+
* `.tf` file gets 400, and an upload over a version already held gets 400,
|
|
21
|
+
* as a deployment policy that disallows redeploy does, unless `redeploy` is
|
|
22
|
+
* set. `cacheNotFound` keeps a new version's versions list answering 404 for
|
|
23
|
+
* that many reads, as Nexus before 3.95 kept a "not found" in its cache.
|
|
24
|
+
* Every request is kept, headers and body included.
|
|
25
|
+
*/
|
|
26
|
+
import { gunzipSync } from "node:zlib";
|
|
27
|
+
import { readZip } from "./zip.js";
|
|
28
|
+
import { basicOf, bearerOf, bodyOf, headersOf, jsonAnswer } from "./fake-http.js";
|
|
29
|
+
const holdsTf = (body) => {
|
|
30
|
+
if (body[0] === 0x50 && body[1] === 0x4b)
|
|
31
|
+
return readZip(body).entries.some((e) => !e.dir && e.path.endsWith(".tf"));
|
|
32
|
+
if (body[0] === 0x1f && body[1] === 0x8b)
|
|
33
|
+
return gunzipSync(body).includes(Buffer.from(".tf"));
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
export function createFakeNexus(o) {
|
|
37
|
+
const requests = [];
|
|
38
|
+
const assets = new Map();
|
|
39
|
+
const issued = new Set();
|
|
40
|
+
const cached = new Map();
|
|
41
|
+
const userOf = (headers) => {
|
|
42
|
+
const b = basicOf(headers.authorization);
|
|
43
|
+
return b && o.users[b.user] === b.password ? b.user : undefined;
|
|
44
|
+
};
|
|
45
|
+
const mayRead = (headers) => {
|
|
46
|
+
if (userOf(headers))
|
|
47
|
+
return true;
|
|
48
|
+
const bearer = bearerOf(headers.authorization);
|
|
49
|
+
return o.bearer !== false && bearer !== undefined && issued.has(bearer);
|
|
50
|
+
};
|
|
51
|
+
const versionOf = (key) => key.split("/").slice(0, 5).join("/");
|
|
52
|
+
const seed = (repo, ns, name, system, version, file, bytes) => void assets.set(`${repo}/${ns}/${name}/${system}/${version}/${file}`, bytes);
|
|
53
|
+
const fetch = async (url, init = {}) => {
|
|
54
|
+
const method = (init.method ?? "GET").toUpperCase();
|
|
55
|
+
const headers = headersOf(init.headers);
|
|
56
|
+
const body = bodyOf(init.body);
|
|
57
|
+
requests.push({ method, url, headers, ...(body ? { body } : {}) });
|
|
58
|
+
const u = new URL(url);
|
|
59
|
+
if (u.host !== o.host)
|
|
60
|
+
throw new TypeError(`fetch failed: the fake answers only ${o.host}, not ${u.host}`);
|
|
61
|
+
const m = /^\/repository\/([^/]+)\/(.*)$/.exec(u.pathname);
|
|
62
|
+
if (!m || !o.repos.includes(decodeURIComponent(m[1])))
|
|
63
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
64
|
+
const repo = decodeURIComponent(m[1]);
|
|
65
|
+
const rest = m[2].split("/").map(decodeURIComponent);
|
|
66
|
+
if (rest.join("/") === "v1/api/token") {
|
|
67
|
+
if (method !== "GET" || o.bearer === false)
|
|
68
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
69
|
+
const user = userOf(headers);
|
|
70
|
+
if (!user)
|
|
71
|
+
return jsonAnswer(401, { message: "Unauthorized" });
|
|
72
|
+
const token = `TerraformBearerToken.fake-${user}-${issued.size + 1}`;
|
|
73
|
+
issued.add(token);
|
|
74
|
+
return jsonAnswer(200, { token });
|
|
75
|
+
}
|
|
76
|
+
if (rest[0] !== "v1" || rest[1] !== "modules")
|
|
77
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
78
|
+
const [ns, name, system] = rest.slice(2, 5);
|
|
79
|
+
const prefix = `${repo}/${ns}/${name}/${system}/`;
|
|
80
|
+
const tail = rest.slice(5);
|
|
81
|
+
if (method === "PUT") {
|
|
82
|
+
if (tail.length !== 2)
|
|
83
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
84
|
+
if (!userOf(headers))
|
|
85
|
+
return jsonAnswer(401, { message: "Unauthorized" });
|
|
86
|
+
if (!body || body.length === 0)
|
|
87
|
+
return jsonAnswer(400, { message: "empty body" });
|
|
88
|
+
let ok = false;
|
|
89
|
+
try {
|
|
90
|
+
ok = holdsTf(body);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
ok = false;
|
|
94
|
+
}
|
|
95
|
+
if (!ok)
|
|
96
|
+
return jsonAnswer(400, { message: "the archive must be a .zip, .tar.gz or .tgz holding .tf files" });
|
|
97
|
+
const k = `${prefix}${tail[0]}/${tail[1]}`;
|
|
98
|
+
const held = [...assets.keys()].some((a) => versionOf(a) === versionOf(k));
|
|
99
|
+
if (held && !o.redeploy)
|
|
100
|
+
return jsonAnswer(400, { message: "Repository does not allow updating assets" });
|
|
101
|
+
assets.set(k, body);
|
|
102
|
+
if (o.cacheNotFound)
|
|
103
|
+
cached.set(`${prefix}`, o.cacheNotFound);
|
|
104
|
+
return new Response(null, { status: 201 });
|
|
105
|
+
}
|
|
106
|
+
if (method !== "GET")
|
|
107
|
+
return jsonAnswer(405, { message: "Method Not Allowed" });
|
|
108
|
+
if (!mayRead(headers))
|
|
109
|
+
return jsonAnswer(401, { message: "Unauthorized" });
|
|
110
|
+
if (tail.length === 1 && tail[0] === "versions") {
|
|
111
|
+
const left = cached.get(prefix) ?? 0;
|
|
112
|
+
if (left > 0) {
|
|
113
|
+
cached.set(prefix, left - 1);
|
|
114
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
115
|
+
}
|
|
116
|
+
const versions = [...new Set([...assets.keys()].filter((k) => k.startsWith(prefix)).map((k) => k.slice(prefix.length).split("/")[0]))];
|
|
117
|
+
if (versions.length === 0)
|
|
118
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
119
|
+
return jsonAnswer(200, { modules: [{ versions: versions.map((version) => ({ version })) }] });
|
|
120
|
+
}
|
|
121
|
+
if (tail.length === 2 && tail[1] === "download") {
|
|
122
|
+
const asset = [...assets.keys()].find((k) => k.startsWith(`${prefix}${tail[0]}/`));
|
|
123
|
+
if (!asset)
|
|
124
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
125
|
+
const file = asset.slice(`${prefix}${tail[0]}/`.length);
|
|
126
|
+
return new Response(null, { status: 204, headers: { "X-Terraform-Get": `${u.origin}/repository/${repo}/v1/modules/${ns}/${name}/${system}/${tail[0]}/${file}` } });
|
|
127
|
+
}
|
|
128
|
+
if (tail.length === 2) {
|
|
129
|
+
const stored = assets.get(`${prefix}${tail[0]}/${tail[1]}`);
|
|
130
|
+
if (!stored)
|
|
131
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
132
|
+
return new Response(new Uint8Array(stored), { status: 200, headers: { "content-type": "application/octet-stream" } });
|
|
133
|
+
}
|
|
134
|
+
return jsonAnswer(404, { message: "Not Found" });
|
|
135
|
+
};
|
|
136
|
+
return { fetch, requests, assets, issued, seed };
|
|
137
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitLab's Terraform module registry as a module target (chant#4603).
|
|
3
|
+
*
|
|
4
|
+
* The one write is GitLab's documented upload
|
|
5
|
+
* (docs.gitlab.com/api/packages/terraform-modules/):
|
|
6
|
+
*
|
|
7
|
+
* PUT /projects/:id/packages/terraform/modules/:name/:system/:version/file
|
|
8
|
+
*
|
|
9
|
+
* with the archive as the body. The token follows chant's forge target
|
|
10
|
+
* (core lifecycle/publish-forge.ts `forgeTokenEnv`): the variable the
|
|
11
|
+
* declaration names, else `GITLAB_TOKEN`, then `CI_JOB_TOKEN`. A job token
|
|
12
|
+
* goes in `JOB-TOKEN` and any other in `PRIVATE-TOKEN`. The API root is the
|
|
13
|
+
* declaration's, else `CI_API_V4_URL`, else gitlab.com's; the project is the
|
|
14
|
+
* declaration's (an id or a full path), else `CI_PROJECT_ID`.
|
|
15
|
+
*
|
|
16
|
+
* GitLab lists a version as soon as it is uploaded, so there is no staging
|
|
17
|
+
* step to hide it: `stage` uploads, and `reveal` reads the version back the
|
|
18
|
+
* way Terraform and OpenTofu do (discovery, versions, download) with the
|
|
19
|
+
* lexicon's registry reader, sending `TF_TOKEN_<host>` (chant#4563), else the
|
|
20
|
+
* upload token, which GitLab also takes as a bearer token on these reads.
|
|
21
|
+
* `held` downloads the version's archive and compares its content digest, so
|
|
22
|
+
* a version holding other content is refused and the same content comes back
|
|
23
|
+
* `present` with nothing sent.
|
|
24
|
+
*
|
|
25
|
+
* GitLab's module API has no call to deprecate a version, so a deprecation
|
|
26
|
+
* stays in the bucket catalog and GitLab shows none. The namespace a GitLab
|
|
27
|
+
* source names is the project's top-level group (`CI_PROJECT_ROOT_NAMESPACE`
|
|
28
|
+
* in CI): the declaration's `namespace`, else the context's.
|
|
29
|
+
*/
|
|
30
|
+
import { type Credential } from "@intentius/chant/lifecycle/publish-credentials";
|
|
31
|
+
import { type ModuleAddress, type ModulePublishTarget, type ModuleTargetDeps } from "./module-target.js";
|
|
32
|
+
/** How a GitLab module target is declared. Every field is optional in GitLab CI. */
|
|
33
|
+
export interface GitlabModuleTargetOptions {
|
|
34
|
+
/** The project the module is uploaded to: its id or its full path. Default `CI_PROJECT_ID`. */
|
|
35
|
+
project?: string;
|
|
36
|
+
/** The API root, such as `https://gitlab.example.com/api/v4`. Default `CI_API_V4_URL`, else gitlab.com's. */
|
|
37
|
+
api?: string;
|
|
38
|
+
/** The variable the token is read from, in place of `GITLAB_TOKEN` then `CI_JOB_TOKEN`. */
|
|
39
|
+
tokenEnv?: string;
|
|
40
|
+
/** The namespace sources name: the project's top-level group. Default: the context's. */
|
|
41
|
+
namespace?: string;
|
|
42
|
+
}
|
|
43
|
+
export declare const GITLAB_DEFAULT_API = "https://gitlab.com/api/v4";
|
|
44
|
+
/** The variables the upload token is read from, in order. */
|
|
45
|
+
export declare const gitlabTokenEnv: (o: Pick<GitlabModuleTargetOptions, "tokenEnv">) => string[];
|
|
46
|
+
/** The API root a target uploads to, without a trailing slash. */
|
|
47
|
+
export declare const gitlabApi: (o: Pick<GitlabModuleTargetOptions, "api">, env: NodeJS.ProcessEnv) => string;
|
|
48
|
+
/** The headers a GitLab token goes in: `JOB-TOKEN` for a CI job token, `PRIVATE-TOKEN` for any other. */
|
|
49
|
+
export declare const gitlabAuthHeader: (token: Credential) => Record<string, string>;
|
|
50
|
+
/** The upload URL for one version. */
|
|
51
|
+
export declare function gitlabUploadUrl(api: string, project: string, address: Pick<ModuleAddress, "name" | "system">, version: string): string;
|
|
52
|
+
export declare function gitlabModuleTarget(options?: GitlabModuleTargetOptions, deps?: ModuleTargetDeps): ModulePublishTarget<"gitlab">;
|
|
53
|
+
//# sourceMappingURL=gitlab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../../src/registry/targets/gitlab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,gDAAgD,CAAC;AAKjG,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAEzB,oFAAoF;AACpF,MAAM,WAAW,yBAAyB;IACxC,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6GAA6G;IAC7G,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,6DAA6D;AAC7D,eAAO,MAAM,cAAc,MAAO,IAAI,CAAC,yBAAyB,EAAE,UAAU,CAAC,KAAG,MAAM,EAAoE,CAAC;AAE3J,kEAAkE;AAClE,eAAO,MAAM,SAAS,MAAO,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,UAAU,KAAG,MAAgF,CAAC;AAE/K,yGAAyG;AACzG,eAAO,MAAM,gBAAgB,UAAW,UAAU,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAsG,CAAC;AAEjL,sCAAsC;AACtC,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtI;AAKD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,yBAA8B,EAAE,IAAI,GAAE,gBAAqB,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CA+ItI"}
|