A member on plunge
plunge is a Pulumi fork with its own state backends. A Pulumi member can run
on it, and chant then runs plunge where it would run pulumi. The member
kind, the graph and the node ids are the same. The plunge-member example in
lexicons/pulumi/examples/ is a workspace with one such member.
How chant decides
Section titled “How chant decides”| Source | Says plunge when | Read |
|---|---|---|
pulumi.member.engine | it is "plunge" | first; when set, it decides |
plywood.yml | engine: plunge, or a backend starting with plunge | when the config sets no engine |
PULUMI_BACKEND_URL | it starts with plunge | after plywood.yml |
Pulumi.yaml backend.url | it starts with plunge (plunge+file://..., plunge://...) | last |
With none of these naming plunge, the member runs stock pulumi. The CLI’s
login state is not read. The plan output prints which source decided.
PUL015 checks one direction only. A config that says engine: "pulumi" while
the resolved engine would be plunge, from plywood.yml, PULUMI_BACKEND_URL
or Pulumi.yaml, runs stock pulumi against a backend it cannot open, and
PUL015 reports that at build time with the source in the message. The reverse,
engine: "plunge" with a stock backend, is never reported, because plunge
opens stock backends and that is a valid setup.
What chant runs
Section titled “What chant runs”| Read | Command | Changes the stack |
|---|---|---|
| graph | none; the export in the index store, else the checked-in stack-export.json | no |
| export after an apply | plunge stack export --stack <name>, from the pulumi-up apply only | no |
| change set | plunge preview --json | no |
| applied outputs | plunge stack output --json --show-secrets=false | no |
| drift | plunge drift --resource <urn> --stream --stack <name>, per resource | no |
| engine facts | plunge graph --json --stack <name>, once per member | no |
| adoption preview | plunge stack adopt --json --stack <name> [--file <file>], from PulumiAdoptOp | no |
| adoption | plunge stack adopt --json --yes --stack <name> [--file <file>], from PulumiAdoptOp after its gate | writes plunge’s records |
runAllowedPlunge refuses any other argv before it reaches the binary, as
ruled on #4476. For
plunge graph it lets through exactly four argv
(#4529):
plunge graph --jsonplunge graph --json --stack <stack>plunge graph --json --versionsplunge graph --json --stack <stack> --versionsFlags go in that order, each at most once. Any outputs or secrets flag is refused, since chant never asks plunge for an output value.
Engine facts
Section titled “Engine facts”plunge graph --json prints the stack’s graph from plunge’s records, in the
engine graph document of #4520.
It reads no live object and makes no provider call. chant reads it two ways:
| Read | Source | What it adds |
|---|---|---|
describeResources | plunge graph --json --stack <name> | each node as a resource, with plunge’s physicalId and its facts on ResourceMetadata.facts; ownership is unknown and no marker is set |
| the graph | a checked-in engine-graph.json beside stack-export.json | nodes[].facts, and the property edges with grain: "property" |
The export’s dependencies and parent edges carry grain: "instance"
on every member. The graph’s provider edges are not taken, since providers
have no node. Facts are for people and for readers that show the graph:
nothing in chant decides from them. plunge’s markers say source: "record",
what its record says it wrote, and its ownership is only bound or
pending.
describeResources leaves --versions off: it costs one version listing
per record. Take the file with the same command the read runs:
plunge graph --json --stack dev > engine-graph.jsonA stock member gets no facts, and chant runs nothing new for it. A plunge
older than plunge graph fails the read, and every entity is then
not-observed with read-failed.
plunge drift --stream prints drift-record NDJSON, one record per line, so
chant decodes it rather than mapping a refresh’s steps. Each record is placed
on a node by the same URN rule the graph uses (@intentius/chant/pulumi-urn).
A resource plunge cannot read, such as a component with no cloud object,
comes back not-observed with plunge’s reason.
The export
Section titled “The export”A stack chant applies with pulumi-up gets its export written to the index
store after each plunge up, as a stock stack does. A stack applied outside
chant checks in the same stack-export.json a stock member does, taken with
plunge:
plunge stack export --file stack-export.jsonEvery check on The stack export applies to it.
Adopting a stock stack
Section titled “Adopting a stock stack”PulumiAdoptOp moves stock Pulumi stacks onto plunge’s records, one wave
per stack, behind a gate:
import { PulumiAdoptOp } from "@intentius/chant-lexicon-pulumi";
export const { op } = PulumiAdoptOp({ name: "adopt-infra", stacks: [{ member: "infra", dir: "./infra", stack: "dev" }],});The Check phase runs chant’s shared bucket check on the bucket the
plunge+ backend URL names and refuses a stack whose bucket fails a
setting that is not waived (allow_insecure on the URL,
PLUNGE_ALLOW_INSECURE, or the stack’s allowInsecure). The Export phase
takes each stack’s stock checkpoint with pulumi stack export --stack <name> into a scratch file, which is the copy to import if you back out.
For each stack, Preview runs plunge stack adopt --json, the gate binds
that document’s digest, and Adopt runs it again with --yes. A stack
coming from Pulumi Cloud sets from: { backend: "https://api.pulumi.com" },
and one exported by hand sets from: { file }; plunge then adopts the
export with --file.
Each gate waits on the workspace ledger until chant approve <op> <gate>,
and the run is recorded there like any Op run. Adoption calls no cloud API.
The next plunge up adds the plunge-stack and plunge-urn tags.