Architecture¶
dss-provisioner follows Terraform's plan/apply model. You declare desired state in YAML, the engine computes a diff against actual state, and apply executes the changes.
Core loop¶
YAML config ──► plan() ──► Plan (diff) ──► apply() ──► DSS API calls
▲ │
│ ▼
State file ◄──────────────────────────── Updated state
- Load — Parse
dss-provisioner.yamlinto a validatedConfigobject - Refresh — Read live DSS state for each tracked resource, update the state file
- Plan — Compare desired resources against state, produce a
PlanofResourceChangeitems - Apply — Execute the plan in dependency order, updating state after each resource
Key components¶
Engine (DSSEngine)¶
The engine is the central orchestrator. It holds references to the provider, state, and handler registry. Its two main methods are:
plan()— Compares desired resources against current state. Optionally refreshes state first (default: yes). Returns aPlancontaining a list ofResourceChangeitems, each with an action:create,update,delete, orno-op.apply()— Executes a plan. Processes changes in topological order (respectingdepends_onand inferred dependencies). Updates the state file after each successful operation. If a resource fails, the error is raised with a partialApplyResultso you can see what succeeded.
State file¶
The state file (.dss-state.json by default) tracks:
- Lineage — A UUID identifying this state's history, used for stale-plan detection
- Serial — Incremented on every write, used for concurrency detection
- Resources — A map of resource addresses to their last-known attributes
- Digest — SHA256 hash of resource attributes, used to detect plan staleness
State is written atomically (temp file + rename) and a .backup copy is kept.
Handlers¶
Handlers implement CRUD operations for each resource type. The engine delegates to the appropriate handler based on resource type. Handler categories:
- VariablesHandler — Reads and writes DSS project variables (singleton per project)
- ZoneHandler — Creates, updates, reads, and deletes DSS flow zones
- GitLibraryHandler — Creates, updates, reads, and deletes DSS Git library references
- DatasetHandler — Creates, updates, reads, and deletes DSS datasets
- RecipeHandler — Creates, updates, reads, and deletes DSS recipes
Dependency graph¶
Resources can declare dependencies explicitly via depends_on or implicitly through recipe inputs/outputs. The engine builds a directed acyclic graph and processes resources in topological order during apply.
If dependencies contain a cycle, the engine raises DependencyCycleError.
Engine semantics¶
- One state file manages one DSS project. Plan/apply will error if the state belongs to a different project (
StateProjectMismatchError). planperforms a refresh by default — reads live DSS state and may persist updates. Disable with--no-refreshorrefresh=False.applyexecutes changes in dependency order with no rollback. If apply fails, state reflects what was completed. TheApplyErrorcarries a partialApplyResult.- Saved plans (via
--out) are checked for staleness via lineage, serial, and state digest before apply. - DSS
${…}variables (e.g.${projectKey}) are resolved transparently during plan comparison so they don't cause false drift.
Partial failure¶
Apply does not support rollback. If a resource fails mid-apply:
- All previously applied resources remain in place and are tracked in state
- The failing resource is not recorded in state
- An
ApplyErroris raised with the partialApplyResultattached - Re-running
plan+applywill retry only the failed and remaining resources