@intentius/chant-lexicon-pulumi 0.0.0-stage → 0.124.54
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 +60 -2
- package/dist/capability-plugin.d.ts +3 -0
- package/dist/capability-plugin.d.ts.map +1 -0
- package/dist/capability-plugin.js +14 -0
- package/dist/change-set.d.ts +159 -0
- package/dist/change-set.d.ts.map +1 -0
- package/dist/change-set.js +347 -0
- package/dist/codegen/docs-cli.d.ts +3 -0
- package/dist/codegen/docs-cli.d.ts.map +1 -0
- package/dist/codegen/docs-cli.js +3 -0
- package/dist/codegen/docs.d.ts +9 -0
- package/dist/codegen/docs.d.ts.map +1 -0
- package/dist/codegen/docs.js +52 -0
- package/dist/codegen/package.d.ts +8 -0
- package/dist/codegen/package.d.ts.map +1 -0
- package/dist/codegen/package.js +56 -0
- package/dist/composites/pulumi-watch-op.d.ts +60 -0
- package/dist/composites/pulumi-watch-op.d.ts.map +1 -0
- package/dist/composites/pulumi-watch-op.js +58 -0
- package/dist/config.d.ts +59 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +29 -0
- package/dist/describe-resources.d.ts +24 -0
- package/dist/describe-resources.d.ts.map +1 -0
- package/dist/describe-resources.js +97 -0
- package/dist/drift-read.d.ts +35 -0
- package/dist/drift-read.d.ts.map +1 -0
- package/dist/drift-read.js +41 -0
- package/dist/drift-record.d.ts +128 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +270 -0
- package/dist/engine-graph.d.ts +75 -0
- package/dist/engine-graph.d.ts.map +1 -0
- package/dist/engine-graph.js +100 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/init-templates.d.ts +23 -0
- package/dist/init-templates.d.ts.map +1 -0
- package/dist/init-templates.js +58 -0
- package/dist/integrity.json +29 -0
- package/dist/lint/audit-catalog.d.ts +21 -0
- package/dist/lint/audit-catalog.d.ts.map +1 -0
- package/dist/lint/audit-catalog.js +139 -0
- package/dist/lint/post-synth/index.d.ts +3 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -0
- package/dist/lint/post-synth/index.js +32 -0
- package/dist/lint/post-synth/member-read-helpers.d.ts +45 -0
- package/dist/lint/post-synth/member-read-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/member-read-helpers.js +103 -0
- package/dist/lint/post-synth/pul001.d.ts +18 -0
- package/dist/lint/post-synth/pul001.d.ts.map +1 -0
- package/dist/lint/post-synth/pul001.js +20 -0
- package/dist/lint/post-synth/pul002.d.ts +18 -0
- package/dist/lint/post-synth/pul002.d.ts.map +1 -0
- package/dist/lint/post-synth/pul002.js +20 -0
- package/dist/lint/post-synth/pul003.d.ts +17 -0
- package/dist/lint/post-synth/pul003.d.ts.map +1 -0
- package/dist/lint/post-synth/pul003.js +21 -0
- package/dist/lint/post-synth/pul004.d.ts +13 -0
- package/dist/lint/post-synth/pul004.d.ts.map +1 -0
- package/dist/lint/post-synth/pul004.js +13 -0
- package/dist/lint/post-synth/pul005.d.ts +12 -0
- package/dist/lint/post-synth/pul005.d.ts.map +1 -0
- package/dist/lint/post-synth/pul005.js +13 -0
- package/dist/lint/post-synth/pul006.d.ts +12 -0
- package/dist/lint/post-synth/pul006.d.ts.map +1 -0
- package/dist/lint/post-synth/pul006.js +13 -0
- package/dist/lint/post-synth/pul007.d.ts +13 -0
- package/dist/lint/post-synth/pul007.d.ts.map +1 -0
- package/dist/lint/post-synth/pul007.js +20 -0
- package/dist/lint/post-synth/pul008.d.ts +12 -0
- package/dist/lint/post-synth/pul008.d.ts.map +1 -0
- package/dist/lint/post-synth/pul008.js +23 -0
- package/dist/lint/post-synth/pul009.d.ts +11 -0
- package/dist/lint/post-synth/pul009.d.ts.map +1 -0
- package/dist/lint/post-synth/pul009.js +19 -0
- package/dist/lint/post-synth/pul010.d.ts +13 -0
- package/dist/lint/post-synth/pul010.d.ts.map +1 -0
- package/dist/lint/post-synth/pul010.js +22 -0
- package/dist/lint/post-synth/pul011.d.ts +12 -0
- package/dist/lint/post-synth/pul011.d.ts.map +1 -0
- package/dist/lint/post-synth/pul011.js +21 -0
- package/dist/lint/post-synth/pul012.d.ts +13 -0
- package/dist/lint/post-synth/pul012.d.ts.map +1 -0
- package/dist/lint/post-synth/pul012.js +20 -0
- package/dist/lint/post-synth/pul013.d.ts +14 -0
- package/dist/lint/post-synth/pul013.d.ts.map +1 -0
- package/dist/lint/post-synth/pul013.js +20 -0
- package/dist/lint/post-synth/pul014.d.ts +12 -0
- package/dist/lint/post-synth/pul014.d.ts.map +1 -0
- package/dist/lint/post-synth/pul014.js +18 -0
- package/dist/lint/post-synth/pul015.d.ts +16 -0
- package/dist/lint/post-synth/pul015.d.ts.map +1 -0
- package/dist/lint/post-synth/pul015.js +19 -0
- package/dist/lint/rules/index.d.ts +5 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/index.js +4 -0
- package/dist/lint/rules/member-dir-absolute.d.ts +22 -0
- package/dist/lint/rules/member-dir-absolute.d.ts.map +1 -0
- package/dist/lint/rules/member-dir-absolute.js +81 -0
- package/dist/lsp/completions.d.ts +5 -0
- package/dist/lsp/completions.d.ts.map +1 -0
- package/dist/lsp/completions.js +120 -0
- package/dist/lsp/documents.d.ts +32 -0
- package/dist/lsp/documents.d.ts.map +1 -0
- package/dist/lsp/documents.js +44 -0
- package/dist/lsp/hover.d.ts +11 -0
- package/dist/lsp/hover.d.ts.map +1 -0
- package/dist/lsp/hover.js +76 -0
- package/dist/lsp/keys.d.ts +35 -0
- package/dist/lsp/keys.d.ts.map +1 -0
- package/dist/lsp/keys.js +146 -0
- package/dist/lsp/object-path.d.ts +16 -0
- package/dist/lsp/object-path.d.ts.map +1 -0
- package/dist/lsp/object-path.js +76 -0
- package/dist/lsp/yaml-cursor.d.ts +29 -0
- package/dist/lsp/yaml-cursor.d.ts.map +1 -0
- package/dist/lsp/yaml-cursor.js +70 -0
- package/dist/manifest.json +6 -0
- package/dist/member-engine.d.ts +8 -0
- package/dist/member-engine.d.ts.map +1 -0
- package/dist/member-engine.js +29 -0
- package/dist/member-outputs.d.ts +43 -0
- package/dist/member-outputs.d.ts.map +1 -0
- package/dist/member-outputs.js +82 -0
- package/dist/meta.json +1 -0
- package/dist/okf/index.md +22 -0
- package/dist/okf/rules/PUL001.md +11 -0
- package/dist/okf/rules/PUL002.md +11 -0
- package/dist/okf/rules/PUL003.md +11 -0
- package/dist/okf/rules/PUL004.md +11 -0
- package/dist/okf/rules/PUL005.md +11 -0
- package/dist/okf/rules/PUL006.md +11 -0
- package/dist/okf/rules/PUL007.md +11 -0
- package/dist/okf/rules/PUL008.md +11 -0
- package/dist/okf/rules/PUL009.md +11 -0
- package/dist/okf/rules/PUL010.md +11 -0
- package/dist/okf/rules/PUL011.md +11 -0
- package/dist/okf/rules/PUL012.md +11 -0
- package/dist/okf/rules/PUL013.md +11 -0
- package/dist/okf/rules/PUL014.md +11 -0
- package/dist/okf/rules/PUL015.md +11 -0
- package/dist/okf/rules/PUL101.md +11 -0
- package/dist/op/activities/index.d.ts +19 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/index.js +17 -0
- package/dist/op/activities/pulumi.d.ts +62 -0
- package/dist/op/activities/pulumi.d.ts.map +1 -0
- package/dist/op/activities/pulumi.js +80 -0
- package/dist/op/activity-contracts.d.ts +34 -0
- package/dist/op/activity-contracts.d.ts.map +1 -0
- package/dist/op/activity-contracts.js +40 -0
- package/dist/op/builders.d.ts +20 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/op/builders.js +19 -0
- package/dist/package-cli.d.ts +3 -0
- package/dist/package-cli.d.ts.map +1 -0
- package/dist/package-cli.js +12 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +201 -0
- package/dist/rules/member-dir-absolute.ts +83 -0
- package/dist/rules/member-read-helpers.ts +122 -0
- package/dist/rules/pul001.ts +38 -0
- package/dist/rules/pul002.ts +38 -0
- package/dist/rules/pul003.ts +43 -0
- package/dist/rules/pul004.ts +32 -0
- package/dist/rules/pul005.ts +31 -0
- package/dist/rules/pul006.ts +31 -0
- package/dist/rules/pul007.ts +35 -0
- package/dist/rules/pul008.ts +35 -0
- package/dist/rules/pul009.ts +32 -0
- package/dist/rules/pul010.ts +42 -0
- package/dist/rules/pul011.ts +38 -0
- package/dist/rules/pul012.ts +35 -0
- package/dist/rules/pul013.ts +35 -0
- package/dist/rules/pul014.ts +32 -0
- package/dist/rules/pul015.ts +37 -0
- package/dist/run.d.ts +201 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +437 -0
- package/dist/serializer.d.ts +8 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/serializer.js +12 -0
- package/dist/skills/chant-pulumi-plunge.md +51 -0
- package/dist/skills/chant-pulumi-stack-export.md +54 -0
- package/dist/skills/chant-pulumi.md +83 -0
- package/dist/stack-outputs.d.ts +18 -0
- package/dist/stack-outputs.d.ts.map +1 -0
- package/dist/stack-outputs.js +55 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/values.d.ts +58 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +155 -0
- package/dist/workspace-member.d.ts +87 -0
- package/dist/workspace-member.d.ts.map +1 -0
- package/dist/workspace-member.js +197 -0
- package/package.json +74 -4
- package/schemas/pulumi.schema.json +34 -0
- package/src/capability-plugin.ts +25 -0
- package/src/change-set.test.ts +235 -0
- package/src/change-set.ts +405 -0
- package/src/codegen/docs-cli.ts +4 -0
- package/src/codegen/docs.ts +58 -0
- package/src/codegen/package.ts +63 -0
- package/src/composites/pulumi-watch-op.test.ts +42 -0
- package/src/composites/pulumi-watch-op.ts +85 -0
- package/src/config.ts +43 -0
- package/src/describe-resources.test.ts +112 -0
- package/src/describe-resources.ts +118 -0
- package/src/drift-read.test.ts +106 -0
- package/src/drift-read.ts +73 -0
- package/src/drift-record.test.ts +197 -0
- package/src/drift-record.ts +326 -0
- package/src/engine-graph.test.ts +141 -0
- package/src/engine-graph.ts +149 -0
- package/src/index.ts +60 -0
- package/src/init-templates.ts +83 -0
- package/src/lint/audit-catalog.test.ts +33 -0
- package/src/lint/audit-catalog.ts +174 -0
- package/src/lint/post-synth/index.ts +35 -0
- package/src/lint/post-synth/member-read-helpers.ts +122 -0
- package/src/lint/post-synth/post-synth.test.ts +199 -0
- package/src/lint/post-synth/pul001.ts +38 -0
- package/src/lint/post-synth/pul002.ts +38 -0
- package/src/lint/post-synth/pul003.ts +43 -0
- package/src/lint/post-synth/pul004.ts +32 -0
- package/src/lint/post-synth/pul005.ts +31 -0
- package/src/lint/post-synth/pul006.ts +31 -0
- package/src/lint/post-synth/pul007.ts +35 -0
- package/src/lint/post-synth/pul008.ts +35 -0
- package/src/lint/post-synth/pul009.ts +32 -0
- package/src/lint/post-synth/pul010.ts +42 -0
- package/src/lint/post-synth/pul011.ts +38 -0
- package/src/lint/post-synth/pul012.ts +35 -0
- package/src/lint/post-synth/pul013.ts +35 -0
- package/src/lint/post-synth/pul014.ts +32 -0
- package/src/lint/post-synth/pul015.ts +37 -0
- package/src/lint/rules/index.ts +7 -0
- package/src/lint/rules/member-dir-absolute.test.ts +37 -0
- package/src/lint/rules/member-dir-absolute.ts +83 -0
- package/src/lsp/completions.test.ts +69 -0
- package/src/lsp/completions.ts +119 -0
- package/src/lsp/documents.ts +48 -0
- package/src/lsp/hover.test.ts +56 -0
- package/src/lsp/hover.ts +83 -0
- package/src/lsp/keys.ts +169 -0
- package/src/lsp/object-path.ts +71 -0
- package/src/lsp/yaml-cursor.ts +85 -0
- package/src/member-engine.ts +30 -0
- package/src/member-outputs.test.ts +317 -0
- package/src/member-outputs.ts +138 -0
- package/src/op/activities/index.ts +18 -0
- package/src/op/activities/pulumi.ts +135 -0
- package/src/op/activity-contracts.ts +54 -0
- package/src/op/builders.ts +30 -0
- package/src/package-cli.ts +14 -0
- package/src/plugin.test.ts +96 -0
- package/src/plugin.ts +222 -0
- package/src/pulumi-urn-node.test.ts +94 -0
- package/src/run.test.ts +327 -0
- package/src/run.ts +542 -0
- package/src/serializer.test.ts +9 -0
- package/src/serializer.ts +15 -0
- package/src/skills/chant-pulumi-plunge.md +51 -0
- package/src/skills/chant-pulumi-stack-export.md +54 -0
- package/src/skills/chant-pulumi.md +83 -0
- package/src/stack-outputs.ts +66 -0
- package/src/testdata/plunge-drift/README.md +10 -0
- package/src/testdata/plunge-drift/assets-drifted.ndjson +3 -0
- package/src/testdata/plunge-drift/component-unsupported.ndjson +3 -0
- package/src/testdata/plunge-drift/role-in-sync.ndjson +3 -0
- package/src/testdata/plunge-drift/settled-empty.ndjson +2 -0
- package/src/testdata/plunge-graph/Pulumi.yaml +4 -0
- package/src/testdata/plunge-graph/README.md +12 -0
- package/src/testdata/plunge-graph/engine-graph.json +158 -0
- package/src/testdata/plunge-graph/stack-export.json +49 -0
- package/src/testdata/plunge-member/Pulumi.yaml +4 -0
- package/src/testdata/plunge-member/README.md +3 -0
- package/src/testdata/plunge-member/stack-export.json +480 -0
- package/src/testdata/plunge-outputs/Pulumi.yaml +9 -0
- package/src/testdata/plunge-outputs/README.md +7 -0
- package/src/testdata/plunge-outputs/stack-export.json +2003 -0
- package/src/testdata/plunge-outputs/stack-output.json +19 -0
- package/src/testdata/pulumi-member/Pulumi.yaml +2 -0
- package/src/testdata/pulumi-member/README.md +50 -0
- package/src/testdata/pulumi-member/recording/Pulumi.dev.yaml +19 -0
- package/src/testdata/pulumi-member/recording/Pulumi.yaml +7 -0
- package/src/testdata/pulumi-member/recording/index.js +47 -0
- package/src/testdata/pulumi-member/recording/package-lock.json +2707 -0
- package/src/testdata/pulumi-member/recording/package.json +9 -0
- package/src/testdata/pulumi-member/stack-export.json +746 -0
- package/src/testdata/pulumi-outputs/Pulumi.yaml +7 -0
- package/src/testdata/pulumi-outputs/README.md +9 -0
- package/src/testdata/pulumi-outputs/preview-replaced.json +2894 -0
- package/src/testdata/pulumi-outputs/preview-settled.json +2894 -0
- package/src/testdata/pulumi-outputs/stack-export.json +1919 -0
- package/src/testdata/pulumi-outputs/stack-output.json +19 -0
- package/src/testdata/pulumi-preview/Pulumi.yaml +7 -0
- package/src/testdata/pulumi-preview/README.md +9 -0
- package/src/testdata/pulumi-preview/preview-create.json +992 -0
- package/src/testdata/pulumi-preview/preview.json +2894 -0
- package/src/testdata/pulumi-preview/stack-export.json +1919 -0
- package/src/testdata/pulumi-refresh/Pulumi.yaml +7 -0
- package/src/testdata/pulumi-refresh/README.md +14 -0
- package/src/testdata/pulumi-refresh/all.json +3742 -0
- package/src/testdata/pulumi-refresh/bucket-edited.json +468 -0
- package/src/testdata/pulumi-refresh/policy-deleted.json +95 -0
- package/src/testdata/pulumi-refresh/queue-edited.json +250 -0
- package/src/testdata/pulumi-refresh/role-same.json +242 -0
- package/src/testdata/pulumi-refresh/secret-edited.json +247 -0
- package/src/testdata/pulumi-refresh/stack-export.json +1907 -0
- package/src/testdata/pulumi-unexported/Pulumi.yaml +2 -0
- package/src/testdata/pulumi-urn-node/Pulumi.yaml +7 -0
- package/src/testdata/pulumi-urn-node/README.md +9 -0
- package/src/testdata/pulumi-urn-node/preview.json +2894 -0
- package/src/testdata/pulumi-urn-node/stack-export.json +1919 -0
- package/src/values.ts +147 -0
- package/src/workspace-kinds.test.ts +47 -0
- package/src/workspace-member.test.ts +126 -0
- package/src/workspace-member.ts +286 -0
- package/workspace-kinds.json +29 -0
package/README.md
CHANGED
|
@@ -1,3 +1,61 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @intentius/chant-lexicon-pulumi
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pulumi lexicon for [chant](https://intentius.io/chant/). It declares no resource types. It supplies the `pulumi` workspace member kind and reads a Pulumi program four ways:
|
|
4
|
+
|
|
5
|
+
| Read | Source | Module |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| the member's graph | the `pulumi stack export` checked in as `stack-export.json` | `src/workspace-member.ts` |
|
|
8
|
+
| its change-set part | `pulumi preview --json` | `src/change-set.ts` |
|
|
9
|
+
| its drift records | `pulumi refresh --preview-only --json --target <urn>`, one resource at a time | `src/drift-record.ts`, `src/drift-read.ts` |
|
|
10
|
+
| its stack outputs, for another member's parameters | `pulumi stack output --json --show-secrets=false` (applied) and `pulumi preview --json` (planned) | `src/stack-outputs.ts`, `src/member-outputs.ts` |
|
|
11
|
+
| engine facts, for a member on plunge | `plunge graph --json --stack <stack>` (`describeResources`), or the checked-in `engine-graph.json` (the graph read) | `src/describe-resources.ts`, `src/engine-graph.ts` |
|
|
12
|
+
|
|
13
|
+
The graph read never runs `pulumi`. The change set and drift run `preview` and `refresh --preview-only`, and the outputs read adds `stack output --json --show-secrets=false`. A member on plunge runs `plunge preview`, `plunge stack output --json --show-secrets=false` and `plunge drift --resource <urn> --stream`. For its engine facts it runs one of exactly four argv: `plunge graph --json`, `plunge graph --json --stack <stack>`, `plunge graph --json --versions` and `plunge graph --json --stack <stack> --versions` ([#4529](https://github.com/INTENTIUS/chant/issues/4529)). An outputs or secrets flag on `plunge graph` is refused. That is the whole list, as ruled on [#4476](https://github.com/INTENTIUS/chant/issues/4476) (2026-10-25), which widened the [#4450](https://github.com/INTENTIUS/chant/issues/4450) ruling's `preview` and `refresh --preview-only` to keep the outputs read and the plunge commands. Nothing else runs (`runAllowedPulumi` and `runAllowedPlunge` refuse any other argv), so chant never changes a stack. With `CHANT_PULUMI_APPLIED_OUTPUTS=export`, the outputs read runs nothing either.
|
|
14
|
+
|
|
15
|
+
## Drift: `chant workspace drift`
|
|
16
|
+
|
|
17
|
+
`chant workspace drift --member <pulumi member> [--resource <urn>] [--stream]` runs `chant lifecycle drift` in the member's reader project, which calls this lexicon's `readDrift`. A stock member is read with one `pulumi refresh --preview-only --json --target <urn>` per resource in its checked-in `stack-export.json`. A member on plunge is read with `plunge drift --resource <urn> --stream` per resource. `--resource` reads one URN. The only read is `refresh`.
|
|
18
|
+
|
|
19
|
+
A member runs on plunge when its config says `engine: "plunge"`, or when `Pulumi.yaml` names a backend URL starting with `plunge` (`plunge+file://...`, `plunge://...`). Only `Pulumi.yaml` is read, never `PULUMI_BACKEND_URL` or login state.
|
|
20
|
+
|
|
21
|
+
## Engine facts for a member on plunge
|
|
22
|
+
|
|
23
|
+
plunge keeps a record per resource, and `plunge graph --json` prints the stack's graph from those records in the engine graph document chant#4520 designed. It makes no provider call and prints no output value. chant reads it two ways ([#4529](https://github.com/INTENTIUS/chant/issues/4529)):
|
|
24
|
+
|
|
25
|
+
- `describeResources` runs `plunge graph --json --stack <stack>` once per member, with the stack the other reads use. Each node becomes a resource keyed like the member graph's node, with plunge's facts on `ResourceMetadata.facts`. Every resource has `ownership: "unknown"` and no marker, so no change set or teardown decides from it.
|
|
26
|
+
- The graph read takes a checked-in `engine-graph.json` beside `stack-export.json`. Its facts go on the nodes (`nodes[].facts`) and its `property` edges join the graph with `grain: "property"`. The export's `dependencies` and `parent` edges carry `grain: "instance"`.
|
|
27
|
+
|
|
28
|
+
plunge's markers say `source: "record"`: what its record says it wrote, not a read of the object. A stock member gets neither read, and chant runs nothing new for it. Record versions (`--versions`) cost one listing per record, so `describeResources` leaves them off.
|
|
29
|
+
|
|
30
|
+
## Outputs into another member's parameters
|
|
31
|
+
|
|
32
|
+
A chant member reads a Pulumi member's outputs with core's `member-outputs` verb (chant#4455):
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { memberOutputsComponent } from "@intentius/chant/components/verbs/member-outputs";
|
|
36
|
+
|
|
37
|
+
export const aws = memberOutputsComponent("aws");
|
|
38
|
+
export const records: Component = {
|
|
39
|
+
name: "records",
|
|
40
|
+
dependsOn: ["aws"],
|
|
41
|
+
deploy: [phase("Apply", [cfnDeploy({ template: "dist/dns.json", inputs: { awsEndpoint: stackOutput("aws", "awsEndpoint") } })])],
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The consumer lists `pulumi` among its lexicons, which brings `pulumiCapabilityPlugin` and its source, `pulumiOutputSource`, for members of kind `pulumi`.
|
|
46
|
+
|
|
47
|
+
- Applied values come from `pulumi stack output --json --show-secrets=false` in the member's directory. With `CHANT_PULUMI_APPLIED_OUTPUTS=export`, chant runs nothing and reads them from the checked-in `stack-export.json`.
|
|
48
|
+
- Planned values come from `pulumi preview --json --show-sames`. A real preview carries no outputs on the stack's `pulumi:pulumi:Stack` step (recorded, #4475), so a preview with nothing to apply gives the checked-in export's outputs and one with changes leaves every output unknown. An output a stack step does carry is read, and one holding Pulumi's unknown sentinel is unknown. The consumer is planned without an unknown output, gets a hole on `aws#outputs` naming it, and is held back on merge until the member applied, then planned again.
|
|
49
|
+
- The plan digest is the member part's `pulumi-preview` digest, so a preview that moves after review moves the consumer's digest.
|
|
50
|
+
- While the preview still has changes, `run` refuses and the consumer is blocked behind the member.
|
|
51
|
+
- Secret outputs are left out of both reads. chant never carries or prints their values.
|
|
52
|
+
- A member on plunge runs the same commands under `plunge`.
|
|
53
|
+
- Both commands run against the member's selected stack.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install --save-dev @intentius/chant @intentius/chant-lexicon-pulumi
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
See the main project LICENSE file.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../src/capability-plugin.ts"],"names":[],"mappings":"AASA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAIzG,eAAO,MAAM,sBAAsB,EAAE,gBAWpC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ownPackageVersion } from "@intentius/chant/components/capability-plugin";
|
|
2
|
+
import { pulumiStackOutputSource } from "./member-outputs.js";
|
|
3
|
+
export const pulumiCapabilityPlugin = {
|
|
4
|
+
name: "pulumi",
|
|
5
|
+
get version() {
|
|
6
|
+
return ownPackageVersion(import.meta.url);
|
|
7
|
+
},
|
|
8
|
+
capabilities() {
|
|
9
|
+
return [];
|
|
10
|
+
},
|
|
11
|
+
engineOutputSources() {
|
|
12
|
+
return [pulumiStackOutputSource];
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The change-set adapter for a Pulumi member (#4453): `pulumi preview --json`
|
|
3
|
+
* into an `@intentius/chant/change-set` part, planner `pulumi`.
|
|
4
|
+
*
|
|
5
|
+
* ## Steps to entries
|
|
6
|
+
*
|
|
7
|
+
* The preview prints one step per resource the program registered, `same`
|
|
8
|
+
* included, and a replace as two or three steps on one URN
|
|
9
|
+
* (`create-replacement`, `replace`, `delete-replaced`). The adapter keeps one
|
|
10
|
+
* entry per URN, at the URN, so `node` comes from the one URN rule
|
|
11
|
+
* (`@intentius/chant/pulumi-urn`, #4456):
|
|
12
|
+
*
|
|
13
|
+
* | step op | action | disruption |
|
|
14
|
+
* |---|---|---|
|
|
15
|
+
* | `create` | create | |
|
|
16
|
+
* | `update` | update | in-place |
|
|
17
|
+
* | `delete` | delete | destroy |
|
|
18
|
+
* | `replace`, `create-replacement`, `delete-replaced` | replace | replace, or destroy when the delete comes first (`deleteBeforeReplace`) |
|
|
19
|
+
* | `same` | no-op | |
|
|
20
|
+
* | `read`, `read-replacement`, `refresh` | read | |
|
|
21
|
+
* | `import` | no-op, importing | |
|
|
22
|
+
* | `import-replacement` | replace, importing | replace |
|
|
23
|
+
* | `discard`, `remove-pending-replace` | forget | |
|
|
24
|
+
*
|
|
25
|
+
* An op the table does not hold is a hole on the member, never a guess.
|
|
26
|
+
*
|
|
27
|
+
* Attributes are top-level inputs, as the change set wants them. A create
|
|
28
|
+
* writes every input. An update or replace writes the keys `detailedDiff`
|
|
29
|
+
* and `diffReasons` name, and every input whose new value holds an unknown.
|
|
30
|
+
* `replaceReasons` and a `detailedDiff` kind ending in `-replace` mark
|
|
31
|
+
* `forcesReplacement`. An input that holds Pulumi's unknown sentinel is
|
|
32
|
+
* `unknown: true` with no `after`: a resource that reads an output of one
|
|
33
|
+
* being created shows its dependent input as unknown. A value that holds a
|
|
34
|
+
* secret is `sensitive: true` with neither side.
|
|
35
|
+
*
|
|
36
|
+
* ## What preview cannot list: `mayAppear`
|
|
37
|
+
*
|
|
38
|
+
* A program may register resources inside an `apply()`. At preview an
|
|
39
|
+
* `apply()` whose input is unknown does not run, so what it would register
|
|
40
|
+
* is never in the steps. Dropping it would make the set look smaller than
|
|
41
|
+
* the apply, so the adapter marks it `mayAppear` instead, on two signals:
|
|
42
|
+
*
|
|
43
|
+
* 1. A component (a step whose state is `custom: false`, not the root stack)
|
|
44
|
+
* whose subtree in the preview holds an unknown, in any input or output,
|
|
45
|
+
* or a create or replace, whose outputs are unknown until apply. Its code
|
|
46
|
+
* may be waiting on that value to register children. It gets one entry
|
|
47
|
+
* at `pulumiMayAppearAddress(<component urn>)`, action `create`, type
|
|
48
|
+
* `unknown`, no attributes, on the component's node.
|
|
49
|
+
* 2. With the last deployment's `pulumi stack export` (`prior`): a resource
|
|
50
|
+
* the export holds and the preview has no step for gets an `update`
|
|
51
|
+
* entry with disruption `unknown`, since a full preview lists every
|
|
52
|
+
* registered resource and only an `apply()` that did not run leaves one
|
|
53
|
+
* out. A `delete` step for a resource under a component signal 1 marks
|
|
54
|
+
* keeps its `delete` and gets `mayAppear`, since the `apply()` may
|
|
55
|
+
* register it again. A preview narrowed with `--target` (`targeted`)
|
|
56
|
+
* lists only its targets, and a failed one stops part way, so signal 2's
|
|
57
|
+
* first half is off for both.
|
|
58
|
+
*
|
|
59
|
+
* A resource registered inside an `apply()` directly under the stack, with
|
|
60
|
+
* no export that holds it, has no component to stand under and is not
|
|
61
|
+
* detected. When the export does hold it and its input is unknown, the
|
|
62
|
+
* preview prints a `delete` for it, which reads as a plain delete. Those are
|
|
63
|
+
* the two cases left out.
|
|
64
|
+
*
|
|
65
|
+
* ## The digest
|
|
66
|
+
*
|
|
67
|
+
* {@link pulumiPreviewDigest}: `computePlanDigest("pulumi-preview", …)` over
|
|
68
|
+
* each step's op, URN, provider, id, inputs before and after, `diffReasons`,
|
|
69
|
+
* `replaceReasons` and `detailedDiff`, sorted by URN and op. It leaves out
|
|
70
|
+
* `config`, `duration`, `diagnostics` and `changeSummary`, and the states'
|
|
71
|
+
* outputs, which at preview are the last deployment's or unknown.
|
|
72
|
+
*
|
|
73
|
+
* The fixtures under `testdata/pulumi-preview` are recorded from pulumi
|
|
74
|
+
* 3.272.0 against the plunge corpus's aws-ts program on floci (#4475). What
|
|
75
|
+
* the recording showed: `preview --json` lists no unchanged resource unless
|
|
76
|
+
* `--show-sames` is passed, which chant's argv does, since signal 2 reads a
|
|
77
|
+
* missing resource as one an `apply()` may register; a replace is one
|
|
78
|
+
* `replace` step at preview, not three; the stack's step carries no planned
|
|
79
|
+
* outputs; a secret is the blinded string `"[secret]"`; and a resource
|
|
80
|
+
* registered inside an `apply()` directly under the stack whose input is
|
|
81
|
+
* unknown (the corpus's `vpc-id` parameter, named after a VPC being
|
|
82
|
+
* replaced) is printed as a `delete`, which this adapter keeps as a plain
|
|
83
|
+
* delete since nothing tells it apart from a removed resource.
|
|
84
|
+
*
|
|
85
|
+
* ## The import graph
|
|
86
|
+
*
|
|
87
|
+
* Like the terraform lexicon's `change-set`, this imports chant's
|
|
88
|
+
* `change-set` types, `lifecycle/plan-digest`, `pulumi-urn` and `./values`,
|
|
89
|
+
* so it bundles without TypeScript, node's process modules or zod (#3421).
|
|
90
|
+
*/
|
|
91
|
+
import type { ChangeSetPart } from "@intentius/chant/change-set";
|
|
92
|
+
import { type Json } from "./values.js";
|
|
93
|
+
/** One resource state on a preview step, `apitype.ResourceV3`, as far as the adapter reads it. */
|
|
94
|
+
export interface PulumiStepState {
|
|
95
|
+
urn?: string;
|
|
96
|
+
custom?: boolean;
|
|
97
|
+
delete?: boolean;
|
|
98
|
+
id?: string;
|
|
99
|
+
type?: string;
|
|
100
|
+
parent?: string;
|
|
101
|
+
inputs?: Json;
|
|
102
|
+
outputs?: Json;
|
|
103
|
+
}
|
|
104
|
+
/** One step of `pulumi preview --json` or `pulumi refresh --preview-only --json`. */
|
|
105
|
+
export interface PulumiStep {
|
|
106
|
+
op?: string;
|
|
107
|
+
urn?: string;
|
|
108
|
+
provider?: string;
|
|
109
|
+
oldState?: PulumiStepState;
|
|
110
|
+
newState?: PulumiStepState;
|
|
111
|
+
diffReasons?: string[];
|
|
112
|
+
replaceReasons?: string[];
|
|
113
|
+
detailedDiff?: Record<string, {
|
|
114
|
+
kind?: string;
|
|
115
|
+
inputDiff?: boolean;
|
|
116
|
+
}> | null;
|
|
117
|
+
}
|
|
118
|
+
/** The steps of a preview or refresh document, or undefined when it has none. */
|
|
119
|
+
export declare function pulumiSteps(doc: unknown): PulumiStep[] | undefined;
|
|
120
|
+
/** One resource of a `pulumi stack export`, as far as the adapter reads it. */
|
|
121
|
+
export interface PulumiExportedResource {
|
|
122
|
+
urn: string;
|
|
123
|
+
type: string;
|
|
124
|
+
custom?: boolean;
|
|
125
|
+
id?: string;
|
|
126
|
+
parent?: string;
|
|
127
|
+
}
|
|
128
|
+
/** The resources of a `pulumi stack export` document (`deployment.resources`). Not one: an empty list. */
|
|
129
|
+
export declare function pulumiExportResources(doc: unknown): PulumiExportedResource[];
|
|
130
|
+
/**
|
|
131
|
+
* The member's plan digest: `computePlanDigest("pulumi-preview", …)` over
|
|
132
|
+
* what each step proposes, sorted by URN and op, so two renderings of one
|
|
133
|
+
* preview agree. See the module comment for what it leaves out.
|
|
134
|
+
*/
|
|
135
|
+
export declare function pulumiPreviewDigest(preview: unknown): string;
|
|
136
|
+
export interface PulumiPreviewPartInput {
|
|
137
|
+
/** The workspace member's name, which names its graph nodes (`<member>/<key>`). */
|
|
138
|
+
member: string;
|
|
139
|
+
/** `pulumi preview --json`, parsed. */
|
|
140
|
+
preview: unknown;
|
|
141
|
+
/** The stack the preview ran against, recorded as `scope`. */
|
|
142
|
+
stack?: string;
|
|
143
|
+
/**
|
|
144
|
+
* The last deployment, as `pulumi stack export` prints it: the member's
|
|
145
|
+
* checked-in `stack-export.json`. With it, a resource the preview leaves
|
|
146
|
+
* out is a `mayAppear` entry rather than silence.
|
|
147
|
+
*/
|
|
148
|
+
prior?: unknown;
|
|
149
|
+
/** The preview was narrowed with `--target`, so it lists only its targets. */
|
|
150
|
+
targeted?: boolean;
|
|
151
|
+
/** The preview failed: the member is failed with this error, and keeps whatever steps it printed. */
|
|
152
|
+
error?: string;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A Pulumi member's part, from its `pulumi preview --json`. Throws when the
|
|
156
|
+
* document has no `steps` and no `error` says why.
|
|
157
|
+
*/
|
|
158
|
+
export declare function pulumiPreviewPart(input: PulumiPreviewPartInput): ChangeSetPart;
|
|
159
|
+
//# sourceMappingURL=change-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFG;AAEH,OAAO,KAAK,EAMV,aAAa,EACd,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAA6E,KAAK,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhH,kGAAkG;AAClG,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,qFAAqF;AACrF,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CAC9E;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,EAAE,GAAG,SAAS,CAGlE;AAED,+EAA+E;AAC/E,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,EAAE,CAI5E;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAe5D;AAyFD,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qGAAqG;IACrG,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,aAAa,CAyH9E"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The change-set adapter for a Pulumi member (#4453): `pulumi preview --json`
|
|
3
|
+
* into an `@intentius/chant/change-set` part, planner `pulumi`.
|
|
4
|
+
*
|
|
5
|
+
* ## Steps to entries
|
|
6
|
+
*
|
|
7
|
+
* The preview prints one step per resource the program registered, `same`
|
|
8
|
+
* included, and a replace as two or three steps on one URN
|
|
9
|
+
* (`create-replacement`, `replace`, `delete-replaced`). The adapter keeps one
|
|
10
|
+
* entry per URN, at the URN, so `node` comes from the one URN rule
|
|
11
|
+
* (`@intentius/chant/pulumi-urn`, #4456):
|
|
12
|
+
*
|
|
13
|
+
* | step op | action | disruption |
|
|
14
|
+
* |---|---|---|
|
|
15
|
+
* | `create` | create | |
|
|
16
|
+
* | `update` | update | in-place |
|
|
17
|
+
* | `delete` | delete | destroy |
|
|
18
|
+
* | `replace`, `create-replacement`, `delete-replaced` | replace | replace, or destroy when the delete comes first (`deleteBeforeReplace`) |
|
|
19
|
+
* | `same` | no-op | |
|
|
20
|
+
* | `read`, `read-replacement`, `refresh` | read | |
|
|
21
|
+
* | `import` | no-op, importing | |
|
|
22
|
+
* | `import-replacement` | replace, importing | replace |
|
|
23
|
+
* | `discard`, `remove-pending-replace` | forget | |
|
|
24
|
+
*
|
|
25
|
+
* An op the table does not hold is a hole on the member, never a guess.
|
|
26
|
+
*
|
|
27
|
+
* Attributes are top-level inputs, as the change set wants them. A create
|
|
28
|
+
* writes every input. An update or replace writes the keys `detailedDiff`
|
|
29
|
+
* and `diffReasons` name, and every input whose new value holds an unknown.
|
|
30
|
+
* `replaceReasons` and a `detailedDiff` kind ending in `-replace` mark
|
|
31
|
+
* `forcesReplacement`. An input that holds Pulumi's unknown sentinel is
|
|
32
|
+
* `unknown: true` with no `after`: a resource that reads an output of one
|
|
33
|
+
* being created shows its dependent input as unknown. A value that holds a
|
|
34
|
+
* secret is `sensitive: true` with neither side.
|
|
35
|
+
*
|
|
36
|
+
* ## What preview cannot list: `mayAppear`
|
|
37
|
+
*
|
|
38
|
+
* A program may register resources inside an `apply()`. At preview an
|
|
39
|
+
* `apply()` whose input is unknown does not run, so what it would register
|
|
40
|
+
* is never in the steps. Dropping it would make the set look smaller than
|
|
41
|
+
* the apply, so the adapter marks it `mayAppear` instead, on two signals:
|
|
42
|
+
*
|
|
43
|
+
* 1. A component (a step whose state is `custom: false`, not the root stack)
|
|
44
|
+
* whose subtree in the preview holds an unknown, in any input or output,
|
|
45
|
+
* or a create or replace, whose outputs are unknown until apply. Its code
|
|
46
|
+
* may be waiting on that value to register children. It gets one entry
|
|
47
|
+
* at `pulumiMayAppearAddress(<component urn>)`, action `create`, type
|
|
48
|
+
* `unknown`, no attributes, on the component's node.
|
|
49
|
+
* 2. With the last deployment's `pulumi stack export` (`prior`): a resource
|
|
50
|
+
* the export holds and the preview has no step for gets an `update`
|
|
51
|
+
* entry with disruption `unknown`, since a full preview lists every
|
|
52
|
+
* registered resource and only an `apply()` that did not run leaves one
|
|
53
|
+
* out. A `delete` step for a resource under a component signal 1 marks
|
|
54
|
+
* keeps its `delete` and gets `mayAppear`, since the `apply()` may
|
|
55
|
+
* register it again. A preview narrowed with `--target` (`targeted`)
|
|
56
|
+
* lists only its targets, and a failed one stops part way, so signal 2's
|
|
57
|
+
* first half is off for both.
|
|
58
|
+
*
|
|
59
|
+
* A resource registered inside an `apply()` directly under the stack, with
|
|
60
|
+
* no export that holds it, has no component to stand under and is not
|
|
61
|
+
* detected. When the export does hold it and its input is unknown, the
|
|
62
|
+
* preview prints a `delete` for it, which reads as a plain delete. Those are
|
|
63
|
+
* the two cases left out.
|
|
64
|
+
*
|
|
65
|
+
* ## The digest
|
|
66
|
+
*
|
|
67
|
+
* {@link pulumiPreviewDigest}: `computePlanDigest("pulumi-preview", …)` over
|
|
68
|
+
* each step's op, URN, provider, id, inputs before and after, `diffReasons`,
|
|
69
|
+
* `replaceReasons` and `detailedDiff`, sorted by URN and op. It leaves out
|
|
70
|
+
* `config`, `duration`, `diagnostics` and `changeSummary`, and the states'
|
|
71
|
+
* outputs, which at preview are the last deployment's or unknown.
|
|
72
|
+
*
|
|
73
|
+
* The fixtures under `testdata/pulumi-preview` are recorded from pulumi
|
|
74
|
+
* 3.272.0 against the plunge corpus's aws-ts program on floci (#4475). What
|
|
75
|
+
* the recording showed: `preview --json` lists no unchanged resource unless
|
|
76
|
+
* `--show-sames` is passed, which chant's argv does, since signal 2 reads a
|
|
77
|
+
* missing resource as one an `apply()` may register; a replace is one
|
|
78
|
+
* `replace` step at preview, not three; the stack's step carries no planned
|
|
79
|
+
* outputs; a secret is the blinded string `"[secret]"`; and a resource
|
|
80
|
+
* registered inside an `apply()` directly under the stack whose input is
|
|
81
|
+
* unknown (the corpus's `vpc-id` parameter, named after a VPC being
|
|
82
|
+
* replaced) is printed as a `delete`, which this adapter keeps as a plain
|
|
83
|
+
* delete since nothing tells it apart from a removed resource.
|
|
84
|
+
*
|
|
85
|
+
* ## The import graph
|
|
86
|
+
*
|
|
87
|
+
* Like the terraform lexicon's `change-set`, this imports chant's
|
|
88
|
+
* `change-set` types, `lifecycle/plan-digest`, `pulumi-urn` and `./values`,
|
|
89
|
+
* so it bundles without TypeScript, node's process modules or zod (#3421).
|
|
90
|
+
*/
|
|
91
|
+
import { computePlanDigest } from "@intentius/chant/lifecycle/plan-digest";
|
|
92
|
+
import { isPulumiNodeless, parsePulumiUrn, pulumiMayAppearAddress, PULUMI_STACK_TYPE } from "@intentius/chant/pulumi-urn";
|
|
93
|
+
import { holdsSecret, holdsUnknown, isObject, isUnknown, propertyKeys, topLevelKey } from "./values.js";
|
|
94
|
+
/** The steps of a preview or refresh document, or undefined when it has none. */
|
|
95
|
+
export function pulumiSteps(doc) {
|
|
96
|
+
if (!isObject(doc) || !Array.isArray(doc.steps))
|
|
97
|
+
return undefined;
|
|
98
|
+
return doc.steps.filter((s) => isObject(s) && typeof s.urn === "string");
|
|
99
|
+
}
|
|
100
|
+
/** The resources of a `pulumi stack export` document (`deployment.resources`). Not one: an empty list. */
|
|
101
|
+
export function pulumiExportResources(doc) {
|
|
102
|
+
const deployment = isObject(doc) && isObject(doc.deployment) ? doc.deployment : undefined;
|
|
103
|
+
const list = deployment && Array.isArray(deployment.resources) ? deployment.resources : [];
|
|
104
|
+
return list.filter((r) => isObject(r) && typeof r.urn === "string" && typeof r.type === "string");
|
|
105
|
+
}
|
|
106
|
+
const byString = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
107
|
+
/**
|
|
108
|
+
* The member's plan digest: `computePlanDigest("pulumi-preview", …)` over
|
|
109
|
+
* what each step proposes, sorted by URN and op, so two renderings of one
|
|
110
|
+
* preview agree. See the module comment for what it leaves out.
|
|
111
|
+
*/
|
|
112
|
+
export function pulumiPreviewDigest(preview) {
|
|
113
|
+
const steps = (pulumiSteps(preview) ?? [])
|
|
114
|
+
.map((s) => ({
|
|
115
|
+
op: s.op ?? null,
|
|
116
|
+
urn: s.urn ?? null,
|
|
117
|
+
provider: s.provider ?? null,
|
|
118
|
+
id: s.newState?.id ?? s.oldState?.id ?? null,
|
|
119
|
+
before: s.oldState?.inputs ?? null,
|
|
120
|
+
after: s.newState?.inputs ?? null,
|
|
121
|
+
diffReasons: [...(s.diffReasons ?? [])].sort(),
|
|
122
|
+
replaceReasons: [...(s.replaceReasons ?? [])].sort(),
|
|
123
|
+
detailedDiff: s.detailedDiff ?? null,
|
|
124
|
+
}))
|
|
125
|
+
.sort((a, b) => byString(`${a.urn}\u0000${a.op}`, `${b.urn}\u0000${b.op}`));
|
|
126
|
+
return computePlanDigest("pulumi-preview", steps);
|
|
127
|
+
}
|
|
128
|
+
const REPLACE_OPS = new Set(["replace", "create-replacement", "delete-replaced"]);
|
|
129
|
+
/** The action and disruption one URN's steps mean, or undefined for an op the change set has no action for. */
|
|
130
|
+
function actionOf(steps) {
|
|
131
|
+
const ops = steps.map((s) => s.op ?? "");
|
|
132
|
+
if (ops.includes("import-replacement"))
|
|
133
|
+
return { action: "replace", disruption: "replace", importing: true };
|
|
134
|
+
if (ops.some((o) => REPLACE_OPS.has(o))) {
|
|
135
|
+
const del = ops.indexOf("delete-replaced");
|
|
136
|
+
const create = ops.indexOf("create-replacement");
|
|
137
|
+
return { action: "replace", disruption: del >= 0 && create >= 0 && del < create ? "destroy" : "replace" };
|
|
138
|
+
}
|
|
139
|
+
if (ops.length !== 1)
|
|
140
|
+
return undefined;
|
|
141
|
+
switch (ops[0]) {
|
|
142
|
+
case "create": return { action: "create" };
|
|
143
|
+
case "update": return { action: "update", disruption: "in-place" };
|
|
144
|
+
case "delete": return { action: "delete", disruption: "destroy" };
|
|
145
|
+
case "same": return { action: "no-op" };
|
|
146
|
+
case "read":
|
|
147
|
+
case "read-replacement":
|
|
148
|
+
case "refresh": return { action: "read" };
|
|
149
|
+
case "import": return { action: "no-op", importing: true };
|
|
150
|
+
case "discard":
|
|
151
|
+
case "remove-pending-replace": return { action: "forget" };
|
|
152
|
+
default: return undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** The state before and after across one URN's steps: the first old state and the last new one. */
|
|
156
|
+
function statesOf(steps) {
|
|
157
|
+
const before = steps.find((s) => isObject(s.oldState))?.oldState;
|
|
158
|
+
const after = [...steps].reverse().find((s) => isObject(s.newState) && s.op !== "delete-replaced" && s.op !== "delete")?.newState;
|
|
159
|
+
return { ...(before ? { before } : {}), ...(after ? { after } : {}) };
|
|
160
|
+
}
|
|
161
|
+
function attributesOf(steps, action, states) {
|
|
162
|
+
if (action !== "create" && action !== "update" && action !== "replace")
|
|
163
|
+
return [];
|
|
164
|
+
const before = isObject(states.before?.inputs) ? states.before.inputs : {};
|
|
165
|
+
const after = isObject(states.after?.inputs) ? states.after.inputs : {};
|
|
166
|
+
const forcing = new Set();
|
|
167
|
+
const named = new Set();
|
|
168
|
+
for (const s of steps) {
|
|
169
|
+
for (const k of s.replaceReasons ?? [])
|
|
170
|
+
forcing.add(topLevelKey(k));
|
|
171
|
+
for (const k of s.diffReasons ?? [])
|
|
172
|
+
named.add(topLevelKey(k));
|
|
173
|
+
for (const [path, d] of Object.entries(s.detailedDiff ?? {})) {
|
|
174
|
+
named.add(topLevelKey(path));
|
|
175
|
+
if (typeof d?.kind === "string" && d.kind.endsWith("-replace"))
|
|
176
|
+
forcing.add(topLevelKey(path));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const keys = action === "create"
|
|
180
|
+
? propertyKeys(after)
|
|
181
|
+
: [...new Set([...named, ...propertyKeys(after).filter((k) => holdsUnknown(after[k]))])].filter((k) => !k.startsWith("__"));
|
|
182
|
+
const beforeOut = isObject(states.before?.outputs) ? states.before.outputs : {};
|
|
183
|
+
const afterOut = isObject(states.after?.outputs) ? states.after.outputs : {};
|
|
184
|
+
const present = (v) => v !== undefined && v !== null;
|
|
185
|
+
const out = [];
|
|
186
|
+
for (const k of keys.sort()) {
|
|
187
|
+
let b = before[k];
|
|
188
|
+
let a = after[k];
|
|
189
|
+
let unknown = holdsUnknown(a);
|
|
190
|
+
// On an update a key the diff names is listed even when both sides read the same: the provider said it changes.
|
|
191
|
+
if (action === "create" && !present(a) && !unknown)
|
|
192
|
+
continue;
|
|
193
|
+
// A key the diff names with no input on either side is an output the provider computes (an SSM parameter's
|
|
194
|
+
// `version`, recorded, #4475): before is the last deployment's output, after the planned output, which a
|
|
195
|
+
// preview leaves empty when the value is known only after apply.
|
|
196
|
+
if (action !== "create" && !present(b) && !present(a) && !unknown && named.has(k)) {
|
|
197
|
+
b = beforeOut[k];
|
|
198
|
+
a = afterOut[k];
|
|
199
|
+
unknown = !present(a) || holdsUnknown(a);
|
|
200
|
+
}
|
|
201
|
+
const hasBefore = action !== "create" && present(b);
|
|
202
|
+
const hasAfter = present(a);
|
|
203
|
+
const sensitive = holdsSecret(b) || holdsSecret(a);
|
|
204
|
+
out.push({
|
|
205
|
+
path: k,
|
|
206
|
+
...(sensitive
|
|
207
|
+
? { sensitive: true }
|
|
208
|
+
: {
|
|
209
|
+
...(hasBefore ? { before: b } : {}),
|
|
210
|
+
...(hasAfter && !unknown ? { after: a } : {}),
|
|
211
|
+
}),
|
|
212
|
+
...(unknown ? { unknown: true } : {}),
|
|
213
|
+
...(forcing.has(k) ? { forcesReplacement: true } : {}),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
const knownId = (id) => (typeof id === "string" && id !== "" && !isUnknown(id) ? id : undefined);
|
|
219
|
+
/**
|
|
220
|
+
* A Pulumi member's part, from its `pulumi preview --json`. Throws when the
|
|
221
|
+
* document has no `steps` and no `error` says why.
|
|
222
|
+
*/
|
|
223
|
+
export function pulumiPreviewPart(input) {
|
|
224
|
+
const steps = pulumiSteps(input.preview);
|
|
225
|
+
if (steps === undefined && input.error === undefined)
|
|
226
|
+
throw new Error('not a pulumi preview --json document: no top-level "steps"');
|
|
227
|
+
const scope = input.stack ? { scope: input.stack } : {};
|
|
228
|
+
const base = { member: input.member, lexicon: "pulumi", planner: "pulumi" };
|
|
229
|
+
// One URN's steps, in the order the preview printed them.
|
|
230
|
+
const byUrn = new Map();
|
|
231
|
+
for (const s of steps ?? []) {
|
|
232
|
+
const list = byUrn.get(s.urn) ?? [];
|
|
233
|
+
list.push(s);
|
|
234
|
+
byUrn.set(s.urn, list);
|
|
235
|
+
}
|
|
236
|
+
const entries = [];
|
|
237
|
+
const holes = [];
|
|
238
|
+
const actions = new Map();
|
|
239
|
+
const states = new Map();
|
|
240
|
+
for (const [urn, list] of byUrn) {
|
|
241
|
+
const parsed = parsePulumiUrn(urn);
|
|
242
|
+
const st = statesOf(list);
|
|
243
|
+
states.set(urn, st);
|
|
244
|
+
const type = st.after?.type ?? st.before?.type ?? parsed?.type ?? "unknown";
|
|
245
|
+
const mapped = actionOf(list);
|
|
246
|
+
if (!mapped) {
|
|
247
|
+
holes.push({ address: urn, type, reason: `pulumi printed ${list.map((s) => s.op ?? "no op").join(", ")} for the URN, which the change set has no action for` });
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
actions.set(urn, mapped.action);
|
|
251
|
+
const id = knownId(st.after?.id) ?? knownId(st.before?.id);
|
|
252
|
+
entries.push({
|
|
253
|
+
...base,
|
|
254
|
+
address: urn,
|
|
255
|
+
type,
|
|
256
|
+
...(parsed ? { name: parsed.name } : {}),
|
|
257
|
+
...(id ? { id } : {}),
|
|
258
|
+
action: mapped.action,
|
|
259
|
+
...(mapped.importing ? { importing: true } : {}),
|
|
260
|
+
...(mapped.disruption ? { disruption: mapped.disruption } : {}),
|
|
261
|
+
...scope,
|
|
262
|
+
attributes: attributesOf(list, mapped.action, st),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
// Signal 1: components whose subtree waits on a value preview does not know.
|
|
266
|
+
const parentOf = new Map();
|
|
267
|
+
for (const [urn, st] of states) {
|
|
268
|
+
const parent = st.after?.parent ?? st.before?.parent;
|
|
269
|
+
if (typeof parent === "string")
|
|
270
|
+
parentOf.set(urn, parent);
|
|
271
|
+
}
|
|
272
|
+
const isComponent = (urn) => {
|
|
273
|
+
const st = states.get(urn);
|
|
274
|
+
const state = st?.after ?? st?.before;
|
|
275
|
+
const type = state?.type ?? parsePulumiUrn(urn)?.type ?? "";
|
|
276
|
+
return state?.custom === false && type !== PULUMI_STACK_TYPE && !isPulumiNodeless(type);
|
|
277
|
+
};
|
|
278
|
+
const waits = (urn) => {
|
|
279
|
+
const action = actions.get(urn);
|
|
280
|
+
if (action === "create" || action === "replace")
|
|
281
|
+
return true;
|
|
282
|
+
const st = states.get(urn);
|
|
283
|
+
return holdsUnknown(st?.after?.inputs) || holdsUnknown(st?.after?.outputs);
|
|
284
|
+
};
|
|
285
|
+
const flagged = new Set();
|
|
286
|
+
for (const urn of byUrn.keys()) {
|
|
287
|
+
if (actions.get(urn) === "delete" || !waits(urn))
|
|
288
|
+
continue;
|
|
289
|
+
// The resource and every component above it, up to the stack.
|
|
290
|
+
const seen = new Set();
|
|
291
|
+
for (let at = urn; at !== undefined && !seen.has(at); at = parentOf.get(at)) {
|
|
292
|
+
seen.add(at);
|
|
293
|
+
if (isComponent(at) && actions.get(at) !== "delete")
|
|
294
|
+
flagged.add(at);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (const component of [...flagged].sort()) {
|
|
298
|
+
entries.push({ ...base, address: pulumiMayAppearAddress(component), type: "unknown", action: "create", mayAppear: true, ...scope, attributes: [] });
|
|
299
|
+
}
|
|
300
|
+
const underFlagged = (urn) => {
|
|
301
|
+
const seen = new Set();
|
|
302
|
+
for (let at = parentOf.get(urn); at !== undefined && !seen.has(at); at = parentOf.get(at)) {
|
|
303
|
+
seen.add(at);
|
|
304
|
+
if (flagged.has(at))
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
return false;
|
|
308
|
+
};
|
|
309
|
+
for (const e of entries) {
|
|
310
|
+
if (e.action === "delete" && e.mayAppear !== true && underFlagged(e.address))
|
|
311
|
+
e.mayAppear = true;
|
|
312
|
+
}
|
|
313
|
+
// Signal 2: what the last deployment holds and the preview never listed.
|
|
314
|
+
// A failed preview stopped part way, so what it did not list says nothing.
|
|
315
|
+
if (input.prior !== undefined && !input.targeted && input.error === undefined) {
|
|
316
|
+
for (const r of pulumiExportResources(input.prior)) {
|
|
317
|
+
if (byUrn.has(r.urn) || isPulumiNodeless(r.type))
|
|
318
|
+
continue;
|
|
319
|
+
const parsed = parsePulumiUrn(r.urn);
|
|
320
|
+
const id = knownId(r.id);
|
|
321
|
+
entries.push({
|
|
322
|
+
...base,
|
|
323
|
+
address: r.urn,
|
|
324
|
+
type: r.type,
|
|
325
|
+
...(parsed ? { name: parsed.name } : {}),
|
|
326
|
+
...(id ? { id } : {}),
|
|
327
|
+
action: "update",
|
|
328
|
+
disruption: "unknown",
|
|
329
|
+
mayAppear: true,
|
|
330
|
+
...scope,
|
|
331
|
+
attributes: [],
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const failed = input.error !== undefined;
|
|
336
|
+
return {
|
|
337
|
+
member: {
|
|
338
|
+
...base,
|
|
339
|
+
...scope,
|
|
340
|
+
status: failed ? "failed" : "planned",
|
|
341
|
+
...(failed ? { error: input.error } : {}),
|
|
342
|
+
planDigest: failed ? null : pulumiPreviewDigest(input.preview),
|
|
343
|
+
holes,
|
|
344
|
+
},
|
|
345
|
+
entries,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-cli.d.ts","sourceRoot":"","sources":["../../src/codegen/docs-cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the docs section for the pulumi lexicon (#4468). Authored pages
|
|
3
|
+
* come from `docs/pages/`; the overview, the rules page and the sidebar are
|
|
4
|
+
* the pipeline's.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateDocs(options?: {
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBjF"}
|