@intentius/chant-lexicon-terraform 0.124.54 → 0.124.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- 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/components/capability-plugin.d.ts +40 -6
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability-plugin.js +174 -30
- package/dist/components/compose-group.d.ts +1 -1
- package/dist/components/compose-group.d.ts.map +1 -1
- package/dist/components/compose-group.js +1 -1
- 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/cone.d.ts +53 -0
- package/dist/cone.d.ts.map +1 -0
- package/dist/cone.js +119 -0
- 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/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/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/integrity.json +7 -4
- 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/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/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/terraform.d.ts +29 -0
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/activities/terraform.js +19 -4
- 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/plugin.d.ts.map +1 -1
- package/dist/plugin.js +5 -0
- 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/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/state/azure-blob.d.ts +8 -67
- package/dist/state/azure-blob.d.ts.map +1 -1
- package/dist/state/azure-blob.js +6 -199
- package/dist/state/gcs.d.ts +7 -61
- package/dist/state/gcs.d.ts.map +1 -1
- package/dist/state/gcs.js +5 -222
- package/dist/state/object-store.d.ts +4 -33
- package/dist/state/object-store.d.ts.map +1 -1
- package/dist/state/object-store.js +4 -17
- package/dist/state/s3.d.ts +11 -58
- package/dist/state/s3.d.ts.map +1 -1
- package/dist/state/s3.js +10 -161
- package/dist/state/store.js +2 -2
- 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/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 +19 -3
- package/src/__fixtures__/drift-record/README.md +5 -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__/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/ci-setup.ts +42 -0
- package/src/components/capability-plugin.test.ts +26 -14
- package/src/components/capability-plugin.ts +185 -31
- package/src/components/compose-group.ts +1 -1
- package/src/components/pr-loop-compose.tofu.e2e.test.ts +1 -1
- package/src/components/pr-loop.tofu.test.ts +1 -1
- 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/cone.ts +138 -0
- package/src/cost-hold.ts +29 -0
- package/src/describe-resources.engine-facts.test.ts +2 -3
- 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/index.ts +3 -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/lock-rows.test.ts +70 -0
- package/src/lock-rows.ts +82 -0
- package/src/lock-timeout.ts +34 -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/terraform.ts +46 -5
- 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/consumers.test.ts +57 -0
- package/src/pin/consumers.ts +95 -0
- package/src/plugin.ts +6 -0
- 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/state/azure-blob.ts +6 -221
- package/src/state/gcs.ts +5 -252
- package/src/state/object-store.ts +4 -32
- package/src/state/s3.ts +10 -182
- package/src/state/store.ts +2 -2
- package/src/state-ops.test.ts +182 -0
- package/src/state-ops.ts +462 -0
- package/src/state-reads.ts +116 -0
- package/src/used-sources.test.ts +75 -0
- package/src/used-sources.ts +204 -0
|
@@ -0,0 +1,157 @@
|
|
|
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 } from "@intentius/chant/terraform/hcl2json";
|
|
26
|
+
import { isJsonConfigFile, jsonConfigTree, selectConfigFiles } from "./hcl/files.js";
|
|
27
|
+
import { impliedProvider, normalizeModuleSource, providerAddress, withoutQuery } from "./registry/source-forms.js";
|
|
28
|
+
/** A block list as hcl2json writes it (an array) or a JSON file may (one object). */
|
|
29
|
+
const bodies = (v) => (Array.isArray(v) ? v : v && typeof v === "object" ? [v] : []);
|
|
30
|
+
const ALL_SUFFIXES = [".tf", ".tofu", ".tf.json", ".tofu.json"];
|
|
31
|
+
/** The configuration files of one module directory, plus terragrunt.hcl when `terragrunt`. */
|
|
32
|
+
function moduleFiles(dir, terragrunt, binary) {
|
|
33
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory())
|
|
34
|
+
return [];
|
|
35
|
+
const names = readdirSync(dir).filter((n) => {
|
|
36
|
+
try {
|
|
37
|
+
return statSync(join(dir, n)).isFile();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const config = binary ? selectConfigFiles(names, binary) : names.filter((n) => ALL_SUFFIXES.some((s) => n.endsWith(s))).sort();
|
|
44
|
+
return terragrunt && names.includes("terragrunt.hcl") ? [...config, "terragrunt.hcl"] : config;
|
|
45
|
+
}
|
|
46
|
+
/** The local name of the provider a resource, data or ephemeral block uses: its `provider` argument's, else its type's prefix. */
|
|
47
|
+
function providerOf(type, body) {
|
|
48
|
+
const ref = typeof body.provider === "string" ? /^(?:\$\{)?([A-Za-z][A-Za-z0-9_-]*)/.exec(body.provider) : null;
|
|
49
|
+
return ref ? ref[1] : type.split("_")[0];
|
|
50
|
+
}
|
|
51
|
+
const isLocal = (source) => /^\.\.?\//.test(source);
|
|
52
|
+
async function readDir(abs, shown, prefix, top, o) {
|
|
53
|
+
const providers = [];
|
|
54
|
+
const calls = [];
|
|
55
|
+
const declared = new Set();
|
|
56
|
+
const implied = new Map();
|
|
57
|
+
const provider = (file, block, source, what) => ({
|
|
58
|
+
kind: "provider",
|
|
59
|
+
file,
|
|
60
|
+
block,
|
|
61
|
+
source,
|
|
62
|
+
normal: providerAddress(source, { binary: o.binary, proxies: o.proxies }) ?? source.trim().toLowerCase(),
|
|
63
|
+
...(what ? { implied: what } : {}),
|
|
64
|
+
});
|
|
65
|
+
for (const name of moduleFiles(abs, top, o.binary)) {
|
|
66
|
+
const file = shown === "." ? name : posix.join(shown, name);
|
|
67
|
+
const text = readFileSync(join(abs, name), "utf-8");
|
|
68
|
+
let tree;
|
|
69
|
+
try {
|
|
70
|
+
tree = (isJsonConfigFile(name) ? jsonConfigTree(text) : await o.parser.parse(file, text));
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
throw new Error(`${file} could not be read (${e.message.split("\n")[0]}), so its module and provider sources are unknown`);
|
|
74
|
+
}
|
|
75
|
+
if (name === "terragrunt.hcl") {
|
|
76
|
+
for (const b of bodies(tree.terraform))
|
|
77
|
+
if (typeof b.source === "string")
|
|
78
|
+
calls.push({ file, block: `${prefix}terraform`, source: b.source });
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
for (const [call, list] of Object.entries(tree.module ?? {})) {
|
|
82
|
+
for (const b of bodies(list))
|
|
83
|
+
if (typeof b.source === "string")
|
|
84
|
+
calls.push({ file, block: `${prefix}module.${call}`, source: b.source });
|
|
85
|
+
}
|
|
86
|
+
for (const t of bodies(tree.terraform)) {
|
|
87
|
+
for (const req of bodies(t.required_providers)) {
|
|
88
|
+
for (const [local, v] of Object.entries(req)) {
|
|
89
|
+
declared.add(local);
|
|
90
|
+
const source = v && typeof v === "object" && typeof v.source === "string" ? v.source : `hashicorp/${local}`;
|
|
91
|
+
providers.push(provider(file, `${prefix}required_providers.${local}`, source));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const local of Object.keys(tree.provider ?? {}))
|
|
96
|
+
if (!implied.has(local))
|
|
97
|
+
implied.set(local, { file, what: `provider "${local}"` });
|
|
98
|
+
for (const kind of ["resource", "data", "ephemeral"]) {
|
|
99
|
+
for (const [type, named] of Object.entries(tree[kind] ?? {})) {
|
|
100
|
+
for (const [name, list] of Object.entries(named ?? {})) {
|
|
101
|
+
for (const b of bodies(list)) {
|
|
102
|
+
const local = providerOf(type, b);
|
|
103
|
+
if (!implied.has(local))
|
|
104
|
+
implied.set(local, { file, what: `${kind} "${type}" "${name}"` });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const [local, at] of implied) {
|
|
111
|
+
const source = declared.has(local) ? undefined : impliedProvider(local);
|
|
112
|
+
if (source)
|
|
113
|
+
providers.push(provider(at.file, `${prefix}provider.${local}`, source, at.what));
|
|
114
|
+
}
|
|
115
|
+
return { providers, calls };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Every module source and provider address the root at `dir` uses, and each
|
|
119
|
+
* local call that could not be followed. Throws, naming the file, when a
|
|
120
|
+
* file cannot be parsed, so a check fails loudly instead of checking less.
|
|
121
|
+
*/
|
|
122
|
+
export async function usedSources(dir, options = {}) {
|
|
123
|
+
const project = options.project ?? dir;
|
|
124
|
+
const o = { ...options, parser: options.parser ?? (await loadHcl2json()) };
|
|
125
|
+
const follow = options.followLocal !== false;
|
|
126
|
+
const used = [];
|
|
127
|
+
const unread = [];
|
|
128
|
+
const shownOf = (abs) => relative(project, abs).split(sep).join("/") || ".";
|
|
129
|
+
const walk = async (rel, prefix, chain, top) => {
|
|
130
|
+
const { providers, calls } = await readDir(join(project, rel), rel, prefix, top, o);
|
|
131
|
+
used.push(...providers);
|
|
132
|
+
for (const c of calls) {
|
|
133
|
+
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 }) });
|
|
134
|
+
if (!follow || !isLocal(c.source))
|
|
135
|
+
continue;
|
|
136
|
+
// A Terragrunt source's `//` marks the directory it copies; the module is the path with it read as one `/`.
|
|
137
|
+
const path = withoutQuery(c.source).replace(/\/\/+/g, "/");
|
|
138
|
+
const next = posix.normalize(posix.join(rel, path)).replace(/\/+$/, "") || ".";
|
|
139
|
+
if (next === ".." || next.startsWith("../")) {
|
|
140
|
+
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" });
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (!existsSync(join(project, next))) {
|
|
144
|
+
unread.push({ file: c.file, block: c.block, source: c.source, why: `${next} does not exist, so the sources it uses cannot be read` });
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (chain.includes(next) || moduleFiles(join(project, next), false, o.binary).length === 0)
|
|
148
|
+
continue;
|
|
149
|
+
await walk(next, `${c.block} > `, [...chain, next], false);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const start = shownOf(dir);
|
|
153
|
+
if (start === ".." || start.startsWith("../"))
|
|
154
|
+
throw new Error(`${dir} is outside the project ${project}`);
|
|
155
|
+
await walk(start, "", [start], true);
|
|
156
|
+
return { used, unread };
|
|
157
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-terraform",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.56",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src/",
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"types": "./dist/pin/index.d.ts",
|
|
35
35
|
"default": "./dist/pin/index.js"
|
|
36
36
|
},
|
|
37
|
+
"./module-catalog": {
|
|
38
|
+
"development": "./src/module-catalog/index.ts",
|
|
39
|
+
"types": "./dist/module-catalog/index.d.ts",
|
|
40
|
+
"default": "./dist/module-catalog/index.js"
|
|
41
|
+
},
|
|
37
42
|
"./terragrunt": {
|
|
38
43
|
"development": "./src/terragrunt/index.ts",
|
|
39
44
|
"types": "./dist/terragrunt/index.d.ts",
|
|
@@ -44,6 +49,16 @@
|
|
|
44
49
|
"types": "./dist/state/index.d.ts",
|
|
45
50
|
"default": "./dist/state/index.js"
|
|
46
51
|
},
|
|
52
|
+
"./registry": {
|
|
53
|
+
"development": "./src/registry/index.ts",
|
|
54
|
+
"types": "./dist/registry/index.d.ts",
|
|
55
|
+
"default": "./dist/registry/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./registry/edge": {
|
|
58
|
+
"development": "./src/registry/edge/index.ts",
|
|
59
|
+
"types": "./dist/registry/edge/index.d.ts",
|
|
60
|
+
"default": "./dist/registry/edge/index.js"
|
|
61
|
+
},
|
|
47
62
|
"./lint/post-synth": {
|
|
48
63
|
"development": "./src/lint/post-synth/index.ts",
|
|
49
64
|
"types": "./dist/lint/post-synth/index.d.ts",
|
|
@@ -59,7 +74,8 @@
|
|
|
59
74
|
"docs": "npx tsx src/codegen/docs-cli.ts",
|
|
60
75
|
"build": "../../scripts/tsc7.sh -p tsconfig.build.json --sourceMap false && tsc-alias -p tsconfig.build.json",
|
|
61
76
|
"prepack": "npm run generate && npm run bundle && npm run validate && npm run build",
|
|
62
|
-
"bundle": "tsx src/package-cli.ts"
|
|
77
|
+
"bundle": "tsx src/package-cli.ts",
|
|
78
|
+
"module-catalog:refresh": "npx tsx src/module-catalog/refresh-cli.ts"
|
|
63
79
|
},
|
|
64
80
|
"devDependencies": {
|
|
65
81
|
"@cdktn/hcl2json": "^0.24.0",
|
|
@@ -72,7 +88,7 @@
|
|
|
72
88
|
"access": "public"
|
|
73
89
|
},
|
|
74
90
|
"peerDependencies": {
|
|
75
|
-
"@intentius/chant": "^0.124.
|
|
91
|
+
"@intentius/chant": "^0.124.56",
|
|
76
92
|
"zod": "^4.3.6"
|
|
77
93
|
},
|
|
78
94
|
"description": "terraform lexicon for chant, existing Terraform root modules as declarable entities",
|
|
@@ -9,3 +9,8 @@ It was not recorded from a run.
|
|
|
9
9
|
|
|
10
10
|
`drift-record.test.ts` also reads the recorded fixtures one directory up: `live-plan.json`,
|
|
11
11
|
`live-ls.json`, `show-state.json`, `show-plan.json` and `live-plan-depth/`.
|
|
12
|
+
|
|
13
|
+
`../drift-rows/` holds two hand-written plans for `drift-rows.test.ts` (#4580), also not recorded
|
|
14
|
+
from a run: `refresh-plan.json`, a stock root's refresh-only plan whose `resource_drift` has an update,
|
|
15
|
+
a delete, a create and a data row, and `live-root-plan.json`, a full plan of a root under live resource
|
|
16
|
+
markers with a create, a delete, an update, both replacement orders, a no-op and two data rows.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format_version": "1.2",
|
|
3
|
+
"terraform_version": "1.9.8",
|
|
4
|
+
"resource_drift": [
|
|
5
|
+
{
|
|
6
|
+
"address": "aws_s3_bucket.ignored",
|
|
7
|
+
"mode": "managed",
|
|
8
|
+
"type": "aws_s3_bucket",
|
|
9
|
+
"change": { "actions": ["update"], "before": { "bucket": "ignored" }, "after": { "bucket": "ignored-too" } }
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"resource_changes": [
|
|
13
|
+
{
|
|
14
|
+
"address": "aws_s3_bucket.assets",
|
|
15
|
+
"mode": "managed",
|
|
16
|
+
"type": "aws_s3_bucket",
|
|
17
|
+
"name": "assets",
|
|
18
|
+
"change": { "actions": ["create"], "before": null, "after": { "bucket": "acme-assets" }, "after_unknown": { "arn": true, "id": true } }
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"address": "aws_sqs_queue.stray",
|
|
22
|
+
"mode": "managed",
|
|
23
|
+
"type": "aws_sqs_queue",
|
|
24
|
+
"name": "stray",
|
|
25
|
+
"change": { "actions": ["delete"], "before": { "name": "acme-stray", "id": "https://sqs.local/000000000000/acme-stray" }, "after": null }
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"address": "aws_lambda_function.api",
|
|
29
|
+
"mode": "managed",
|
|
30
|
+
"type": "aws_lambda_function",
|
|
31
|
+
"name": "api",
|
|
32
|
+
"change": { "actions": ["update"], "before": { "function_name": "acme-api", "memory_size": 256, "version": "7" }, "after": { "function_name": "acme-api", "memory_size": 512 }, "after_unknown": { "version": true } }
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"address": "aws_iam_role.deployer",
|
|
36
|
+
"mode": "managed",
|
|
37
|
+
"type": "aws_iam_role",
|
|
38
|
+
"name": "deployer",
|
|
39
|
+
"change": { "actions": ["delete", "create"], "before": { "name": "acme-deployer-old", "arn": "arn:aws:iam::000000000000:role/acme-deployer-old" }, "after": { "name": "acme-deployer" }, "after_unknown": { "arn": true } }
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"address": "aws_security_group.edge",
|
|
43
|
+
"mode": "managed",
|
|
44
|
+
"type": "aws_security_group",
|
|
45
|
+
"name": "edge",
|
|
46
|
+
"change": { "actions": ["create", "delete"], "before": { "name": "", "id": "sg-0001" }, "after": { "name": "" }, "after_unknown": { "id": true } }
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"address": "aws_s3_bucket.steady",
|
|
50
|
+
"mode": "managed",
|
|
51
|
+
"type": "aws_s3_bucket",
|
|
52
|
+
"name": "steady",
|
|
53
|
+
"change": { "actions": ["no-op"], "before": { "bucket": "acme-steady" }, "after": { "bucket": "acme-steady" } }
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"address": "data.aws_region.here",
|
|
57
|
+
"mode": "data",
|
|
58
|
+
"type": "aws_region",
|
|
59
|
+
"name": "here",
|
|
60
|
+
"change": { "actions": ["read"], "before": null, "after": { "name": "us-east-1" } }
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"address": "data.aws_caller_identity.me",
|
|
64
|
+
"mode": "data",
|
|
65
|
+
"type": "aws_caller_identity",
|
|
66
|
+
"name": "me",
|
|
67
|
+
"change": { "actions": ["update"], "before": { "account_id": "000000000000" }, "after": { "account_id": "000000000001" } }
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format_version": "1.2",
|
|
3
|
+
"terraform_version": "1.9.8",
|
|
4
|
+
"prior_state": {
|
|
5
|
+
"values": {
|
|
6
|
+
"root_module": {
|
|
7
|
+
"resources": [
|
|
8
|
+
{ "address": "aws_s3_bucket.logs", "mode": "managed", "type": "aws_s3_bucket", "values": { "bucket": "acme-logs", "tags": { "team": "data" } } },
|
|
9
|
+
{ "address": "aws_lambda_function.worker", "mode": "managed", "type": "aws_lambda_function", "values": { "function_name": "acme-worker", "memory_size": 128 } },
|
|
10
|
+
{ "address": "aws_iam_role.runner", "mode": "managed", "type": "aws_iam_role", "values": { "name": "acme-runner", "arn": "arn:aws:iam::000000000000:role/acme-runner" } }
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"resource_drift": [
|
|
16
|
+
{
|
|
17
|
+
"address": "aws_s3_bucket.logs",
|
|
18
|
+
"mode": "managed",
|
|
19
|
+
"type": "aws_s3_bucket",
|
|
20
|
+
"name": "logs",
|
|
21
|
+
"change": { "actions": ["update"], "before": { "bucket": "acme-logs", "tags": { "team": "data" } }, "after": { "bucket": "acme-logs", "tags": { "team": "ops" } } }
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"address": "aws_lambda_function.worker",
|
|
25
|
+
"mode": "managed",
|
|
26
|
+
"type": "aws_lambda_function",
|
|
27
|
+
"name": "worker",
|
|
28
|
+
"change": { "actions": ["delete"], "before": { "function_name": "acme-worker", "memory_size": 128 }, "after": null }
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"address": "aws_sqs_queue.jobs",
|
|
32
|
+
"mode": "managed",
|
|
33
|
+
"type": "aws_sqs_queue",
|
|
34
|
+
"name": "jobs",
|
|
35
|
+
"change": { "actions": ["create"], "before": null, "after": { "name": "acme-jobs", "id": "https://sqs.local/000000000000/acme-jobs" } }
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"address": "aws_iam_role.runner",
|
|
39
|
+
"mode": "managed",
|
|
40
|
+
"type": "aws_iam_role",
|
|
41
|
+
"name": "runner",
|
|
42
|
+
"change": { "actions": ["update"], "before": { "name": "", "arn": "arn:aws:iam::000000000000:role/acme-runner" }, "after": { "name": "", "arn": "arn:aws:iam::000000000000:role/acme-runner", "max_session_duration": 7200 } }
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"address": "data.aws_caller_identity.me",
|
|
46
|
+
"mode": "data",
|
|
47
|
+
"type": "aws_caller_identity",
|
|
48
|
+
"name": "me",
|
|
49
|
+
"change": { "actions": ["update"], "before": { "account_id": "000000000000" }, "after": { "account_id": "000000000001" } }
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"resource_changes": [
|
|
53
|
+
{
|
|
54
|
+
"address": "aws_s3_bucket.logs",
|
|
55
|
+
"mode": "managed",
|
|
56
|
+
"type": "aws_s3_bucket",
|
|
57
|
+
"name": "logs",
|
|
58
|
+
"change": { "actions": ["no-op"], "before": { "bucket": "acme-logs", "tags": { "team": "ops" } }, "after": { "bucket": "acme-logs", "tags": { "team": "ops" } } }
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
provider "google" {}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
aws = {
|
|
4
|
+
source = "hashicorp/aws"
|
|
5
|
+
version = "~> 5.0"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module "vpc" {
|
|
11
|
+
source = "terraform-aws-modules/vpc/aws"
|
|
12
|
+
version = "5.1.0"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module "net" {
|
|
16
|
+
source = "./modules/net"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module "gone" {
|
|
20
|
+
source = "./modules/missing"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module "outside" {
|
|
24
|
+
source = "../../outside"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
resource "random_id" "x" {
|
|
28
|
+
byte_length = 4
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resource "terraform_data" "t" {}
|
package/src/ci-setup.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The engine install lines a Terraform project's pull request pipeline runs
|
|
3
|
+
* in chant's default image (#4550, `LexiconPlugin.ciSetup`): OpenTofu, and
|
|
4
|
+
* choudoufu when a root runs it. Each line skips the install when the binary
|
|
5
|
+
* is already on PATH.
|
|
6
|
+
*
|
|
7
|
+
* Whether a root runs choudoufu is read from the text of the project's
|
|
8
|
+
* `chant.config.ts` (`binary: "choudoufu"`), never by running it, as lexicon
|
|
9
|
+
* detection reads source.
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { PR_LOOP_SETUP } from "@intentius/chant/components/pr-pipeline";
|
|
14
|
+
|
|
15
|
+
/** The choudoufu release the default lines install. A product's images pin their own. */
|
|
16
|
+
export const CHOUDOUFU_CI_VERSION = "0.31.0";
|
|
17
|
+
|
|
18
|
+
/** choudoufu into /usr/local/bin from its release archive. */
|
|
19
|
+
export function choudoufuInstallLine(version = CHOUDOUFU_CI_VERSION): string {
|
|
20
|
+
const arch = `$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')`;
|
|
21
|
+
const url = `https://github.com/INTENTIUS/choudoufu/releases/download/v${version}/choudoufu_v${version}_linux_${arch}.tar.gz`;
|
|
22
|
+
return `command -v choudoufu >/dev/null 2>&1 || (mkdir -p /tmp/choudoufu && curl -fsSL "${url}" | tar -xz -C /tmp/choudoufu && install "$(find /tmp/choudoufu -type f -name choudoufu | head -n 1)" /usr/local/bin/choudoufu)`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Whether the project's config names choudoufu as a root's binary. */
|
|
26
|
+
export function usesChoudoufu(dir: string): boolean {
|
|
27
|
+
for (const name of ["chant.config.ts", "chant.config.mts", "chant.config.js"]) {
|
|
28
|
+
const file = join(dir, name);
|
|
29
|
+
if (!existsSync(file)) continue;
|
|
30
|
+
try {
|
|
31
|
+
if (/binary\s*:\s*["']choudoufu["']/.test(readFileSync(file, "utf-8"))) return true;
|
|
32
|
+
} catch {
|
|
33
|
+
// unreadable: no choudoufu line
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The lines for the project at `dir`. */
|
|
40
|
+
export function terraformCiSetup(ctx: { dir: string }): string[] {
|
|
41
|
+
return [...PR_LOOP_SETUP, ...(usesChoudoufu(ctx.dir) ? [choudoufuInstallLine()] : [])];
|
|
42
|
+
}
|
|
@@ -24,6 +24,9 @@ const planTexts: Array<boolean | undefined> = [];
|
|
|
24
24
|
let planError: Error | undefined;
|
|
25
25
|
|
|
26
26
|
vi.mock("../op/activities/terraform", () => ({
|
|
27
|
+
// The exit constants exit-codes.ts maps choudoufu's statuses with (#4553), as the module has them.
|
|
28
|
+
CHOUDOUFU_APPROVAL_EXIT_CODE: 3,
|
|
29
|
+
CHOUDOUFU_WAVE_EXIT: { landed: 0, error: 1, setMoved: 3, rootFailed: 4 },
|
|
27
30
|
choudoufuWaveRoot: vi.fn(async () => waveRoot),
|
|
28
31
|
choudoufuPlanSet: vi.fn(async (args: { root: string }) => {
|
|
29
32
|
calls.push(`plan-set ${args.root}`);
|
|
@@ -52,7 +55,8 @@ vi.mock("../op/activities/terraform", () => ({
|
|
|
52
55
|
planTargets.push(args.targets);
|
|
53
56
|
planTexts.push(args.text);
|
|
54
57
|
if (planError) throw planError;
|
|
55
|
-
|
|
58
|
+
// `dir` as the real result has it (#4545 writes the plan document beside the plan file there).
|
|
59
|
+
return { planFile: "chant.tfplan", dir: `/x/${args.root}`, planDigest: `jcs1-sha256:${args.root}`, json: planJson, ...(changeSet ? { changeSet } : {}) };
|
|
56
60
|
}),
|
|
57
61
|
terraformApply: vi.fn(async (args: { root: string; planFile: string }) => {
|
|
58
62
|
calls.push(`apply ${args.root} ${args.planFile}`);
|
|
@@ -133,7 +137,8 @@ describe("terraform-apply on a choudoufu root in a gated wave (#3459)", () => {
|
|
|
133
137
|
expect(calls).toEqual(["plan-set e01"]);
|
|
134
138
|
expect(planned.member).toBe("e01");
|
|
135
139
|
expect(planned.planDigest).toBe("jcs1-sha256:e01");
|
|
136
|
-
|
|
140
|
+
// #4552: the set path keeps the root's lock rows beside the plan (none here: the fake set's plan has no changes).
|
|
141
|
+
expect(planned.artifact).toEqual({ ...wavePlan, lockRows: [] });
|
|
137
142
|
expect(planned.changeSet).toEqual({ member: { member: "e01", nativeDigest: "sha256:root-e01" }, entries: [] });
|
|
138
143
|
});
|
|
139
144
|
|
|
@@ -203,7 +208,7 @@ describe("terraform-apply on a choudoufu root in a gated wave (#3459)", () => {
|
|
|
203
208
|
|
|
204
209
|
describe("terraform-apply", () => {
|
|
205
210
|
test("the plugin contributes it", () => {
|
|
206
|
-
expect(terraformCapabilityPlugin.capabilities().map((c) => c.kind)).toEqual(["terraform-apply"]);
|
|
211
|
+
expect(terraformCapabilityPlugin.capabilities().map((c) => c.kind)).toEqual(["terraform-apply", "terraform-state-unlock", "terraform-state-push", "terraform-copy"]);
|
|
207
212
|
});
|
|
208
213
|
|
|
209
214
|
test("plan inits and plans the root, with its vars, and names the root as the member", async () => {
|
|
@@ -341,17 +346,24 @@ describe("terraform-apply, continued", () => {
|
|
|
341
346
|
expect(calls).not.toContain("output app");
|
|
342
347
|
});
|
|
343
348
|
|
|
344
|
-
test
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
349
|
+
test("choudoufu's approval-mismatch refusal of the wave's plan throws core's plan-moved mark, so the command exits moved (#3997, #4553)", async () => {
|
|
350
|
+
applyResult = { applied: false, refused: "approval-mismatch", refusal: "refused" };
|
|
351
|
+
const err = await terraformApplyCapability
|
|
352
|
+
.run({ env: "test", component: "app", plans: { app: { planFile: "chant.tfplan", planDigest: "d" } } }, { root: "app" })
|
|
353
|
+
.catch((e: unknown) => e);
|
|
354
|
+
expect(err).toBeInstanceOf(TerraformPlanMovedError);
|
|
355
|
+
expect(isPlanMovedError(err)).toBe(true);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
test("choudoufu's wrong-estate refusal is an ordinary failure: the pipeline handed the wrong file, and no approval fixes that (#4553)", async () => {
|
|
359
|
+
applyResult = { applied: false, refused: "wrong-estate", refusal: "refused" };
|
|
360
|
+
const err = await terraformApplyCapability
|
|
361
|
+
.run({ env: "test", component: "app", plans: { app: { planFile: "chant.tfplan", planDigest: "d" } } }, { root: "app" })
|
|
362
|
+
.catch((e: unknown) => e);
|
|
363
|
+
expect(err).toBeInstanceOf(Error);
|
|
364
|
+
expect(err).not.toBeInstanceOf(TerraformPlanMovedError);
|
|
365
|
+
expect(isPlanMovedError(err)).toBe(false);
|
|
366
|
+
});
|
|
355
367
|
|
|
356
368
|
test("a refusal of a plan this run made itself is an ordinary failure: the next run plans afresh", async () => {
|
|
357
369
|
applyResult = { applied: false, refused: "approval-mismatch", refusal: "refused" };
|