Documentation
¶
Overview ¶
Package stateless implements OpenTofu's stateless mode: a run mode with no authoritative state file, no backend, and no lock. Identity is recovered from the live system on every operation instead of being read from a stored record.
Projections ¶
The state data structure does not disappear; its authority does. A projection is an ephemeral prior-state, built at the start of an operation by reading the live system and discarded once the operation completes. It is fed to the unchanged plan engine in place of a state read and is never persisted. Same shape as a states.State, none of the authority: nothing downstream trusts a projection to be correct, because nothing depends on it surviving past the run that built it.
Contrast with authoritative state, whose test is that a wrong record makes OpenTofu do the wrong thing to the world. A wrong projection costs at most a re-plan.
Admission ¶
A resource type participates in stateless mode only if its identity is recoverable with no memory. Four paths admit a resource, strongest first:
- Client-assigned identity: the name is already in the configuration (a bucket name, a role name, a log group name). Nothing to recover.
- Marker: the resource carries ownership tags, defined in live/MARKERS.md, and is found by a tag-filtered list call.
- Parent-derived: identity is a composite key built from already-admitted parents, such as a route keyed by route table and destination, or an association keyed by subnet and route table.
- List and content match: the provider's list protocol enumerates candidates and binding proceeds by content; identical siblings bind as a fungible set (see Count below).
A resource type with none of these four paths is out of the stateless subset and is rejected by lint before a projection is ever built.
Foreign resources ¶
A live resource of an in-scope type with no admission path binding it to configuration is foreign: unrecognized, unmanaged, and never auto-deleted. Stateless mode reports it for review rather than guessing whether it should be adopted or destroyed. A foreign resource that happens to match a declared-but-unbound resource is a bind candidate, surfaced for explicit adoption and never bound automatically.
Count ¶
count survives stateless mode as cardinality over a fungible set rather than as a positional index. Each instance carries a tofu-slot marker: a stable, opaque identifier assigned once at creation and never reused. Binding N declared instances against M live, owned instances is set matching, not index matching: a deficit creates new slots, a surplus deletes the highest slots. Nothing about identity depends on count.index, which is why count.index is banned from identity-bearing resource arguments while the count = var.enabled ? 1 : 0 idiom keeps working unchanged.
Where the phases land ¶
The projection is built and consumed at three seams in the existing codebase, not in a parallel state system:
- internal/states/statemgr: Filesystem is the model for a projection manager. A projection manager's Refresh/State builds its snapshot from live reads instead of a file, and Persist writes nothing (or, for the optional snapshot cache, a scrubbed, observational-only record that no code path reads back as truth).
- Import machinery in internal/tofu: resource identity is merged upstream (opentofu#2854); the same import-by-identity path that backs tofu import is how a projection materializes a states.State for the client-named and parent-derived admission paths.
- The provider list protocol: the mechanism behind admission path 4 and behind tag-filtered marker discovery. Core-side client support tracks the shape of opentofu#3787 to stay mergeable with upstream.
This package holds the model. Concrete implementations live in its subpackages: lint, identity, discovery, stamp, projection, and the rest. The operator-facing specs are in stateless/.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package discovery finds the live resources of a stateless estate by their ownership markers and binds them to the addresses that declare them.
|
Package discovery finds the live resources of a stateless estate by their ownership markers and binds them to the addresses that declare them. |
|
Package flocitest holds the gate, the fixture paths and the container bookkeeping that the floci integration tests share.
|
Package flocitest holds the gate, the fixture paths and the container bookkeeping that the floci integration tests share. |
|
Package foreign classifies the live resources an estate does not own, and is the safety property of stateless mode: a live resource nobody claims is surfaced, and is never a deletion candidate.
|
Package foreign classifies the live resources an estate does not own, and is the safety property of stateless mode: a live resource nobody claims is surfaced, and is never a deletion candidate. |
|
Package identity classifies the identity of every managed resource instance in a configuration, using nothing but the configuration itself.
|
Package identity classifies the identity of every managed resource instance in a configuration, using nothing but the configuration itself. |
|
Package lifecycle holds five integration tests and nothing else: the lifecycle test itself (P4.1), the snapshot test (P4.2), the exactness test (P5.1), the crash-mid-apply test (the concurrency taxonomy's crash row, run rather than argued), and the existence-flavor receipt test (RA.6).
|
Package lifecycle holds five integration tests and nothing else: the lifecycle test itself (P4.1), the snapshot test (P4.2), the exactness test (P5.1), the crash-mid-apply test (the concurrency taxonomy's crash row, run rather than argued), and the existence-flavor receipt test (RA.6). |
|
Package lint is the stateless-mode subset check: the pass that decides whether a configuration can be planned with no authoritative state at all.
|
Package lint is the stateless-mode subset check: the pass that decides whether a configuration can be planned with no authoritative state at all. |
|
Package listclient is stateless mode's client for the provider list protocol: the ListResource server-streaming RPC and the list resource schemas that parameterize it.
|
Package listclient is stateless mode's client for the provider list protocol: the ListResource server-streaming RPC and the list resource schemas that parameterize it. |
|
Package markers is live/MARKERS.md in code: the ownership tag keys, the escaping rule that lets a resource address live in a tag value, and the reading of those tags off a live object.
|
Package markers is live/MARKERS.md in code: the ownership tag keys, the escaping rule that lets a resource address live in a tag value, and the reading of those tags off a live object. |
|
Package mv performs the rename operation stateless mode has instead of `moved` blocks and state surgery: it rewrites the tofu-address ownership marker on one live resource.
|
Package mv performs the rename operation stateless mode has instead of `moved` blocks and state surgery: it rewrites the tofu-address ownership marker on one live resource. |
|
Package projection materializes an ephemeral prior state by reading the live system.
|
Package projection materializes an ephemeral prior state by reading the live system. |
|
Package slots is the set matcher for count instances: the rule that turns "N declared instances and M live resources" into a binding, without any index participating in identity.
|
Package slots is the set matcher for count instances: the rule that turns "N declared instances and M live resources" into a binding, without any index participating in identity. |
|
Package stamp makes ownership markers something the tool guarantees rather than something the configuration author remembered to write.
|
Package stamp makes ownership markers something the tool guarantees rather than something the configuration author remembered to write. |