Skip to navigation

Plan, apply, and reports

The commands here use --local. Use --target DESTINATION instead to run them over SSH.

Plan and noop

rivet plan BUNDLE --local and rivet apply BUNDLE --local --noop inspect each resource and predict what would change. They make no changes and create no lock, journal, or temporary files. They don’t run file validators or refresh apt indexes. Exec guards (only_if, unless) do run, so keep them read-only.

A plan is a snapshot, not a promise. If a prerequisite would change, its dependents are reported as deferred, because Rivet can’t inspect a state that doesn’t exist yet. Apt candidates can also be uncertain until the index is refreshed.

rivet run --noop first acquires and prepares the catalog, which can authenticate, write the artifact cache, and run custom fact scripts, and then predicts the same way.

Apply

Before taking the host lock, apply checks the bundle against fresh host facts: integrity, platform, required capabilities, host identity, and reserved paths. It also checks that no two resources claim the same host object in incompatible ways, for example two SSH keys with conflicting permission policies on one authorized_keys file. A conflict stops the run before anything changes.

Resources then run one at a time, in dependency order. For each resource, Rivet:

  1. Inspects the current state.
  2. Records its intent, and any refreshes it will cause, in the journal.
  3. Makes the change, within the resource’s timeout.
  4. Inspects again to verify the result.
  5. Marks the work complete and delivers any refreshes that are ready.

Properties you didn’t declare are left alone. A failed resource blocks its dependents; unrelated resources continue. Each resource commits on its own: there is no transaction across the host or across a module, and no automatic rollback.

meta.noop = true keeps a single resource read-only during a real apply. On a module it applies to every resource inside, and children can’t turn it off. If a noop resource would change, its dependents are deferred, and an apply with deferred work doesn’t report success.

Report statuses

StatusMeaning
unchangedAlready in the desired state, or the work changed nothing managed.
changedA managed property was changed and verified.
would_changeA noop or plan predicts a change.
failedInspection, change, verification, or recovery failed.
blockedA prerequisite failed, resources conflict, or earlier interrupted work can’t be resumed.
deferredA prerequisite’s pending change makes a reliable check impossible now.
skippedPolicy prevented work, for example a guard, or a refresh-only exec with no refresh queued.

Text output prints one line per resource: the status, the resource ID, the changed properties in brackets, and an optional message. Shared actions, such as a systemd daemon reload, follow on Action: lines. For example:

Changed file.unit [ensure]
Changed service.example [state]
Action: daemon_reload

A failed result may also say (partial change), meaning the host may have been modified before the failure, or (uncertain), meaning the outcome needs checking. Look at the journal rather than assuming a failed run changed nothing.

JSON report

--format json prints the full report. Each resource result has id, status, changed_properties, message, partial_change, uncertain, duration_ms, operation_timeout_ms, and source. Successful commands that aren’t sensitive also include their output, truncated if large.

The run itself has run_id, catalog_digest, host_identity, noop, start and end times, resources, recovery, counts of unresolved intents and refreshes, and actions.

rivet run --format json wraps the report in run and adds provenance (environment, release, and promotion generation), cache (hits, downloads, downloaded_bytes), and offline. With --prepare-only, it prints prepared and catalog_digest instead.