saltstack/salt — Issue #709: predicates, transactions and the partial state problem
Author: teichopsia
Created: 2012-02-16 21:00:17+00:00
State: open

apologies if any of my assumptions are incorrect. they were gleaned from docs, some source code walks and #salt discussion. I am not a puppet/cf/chef user so I don't know if there's a better term for this topic either.

Does salt plan on offering guaranteed states? Right now if you call highstate on a minion, you have no way to know whether the state actually exists in its entirety on said minion, without sifting through what could be a monumentally long result string. the usual mechanic of checking return codes for each id resolution seems... difficult at best.

To me that means the term state is a misnomer as understood in the FSA/FSM vernacular. Rather than moving from one state to another state deterministically, you can in fact be in a limbo between states due to partial solutions completing. a subsequent highstate to deploy a new unrelated state and assumes the previous highstate completed entirely, can in fact never be safe in that assumption.

As I understand salt, salt by default enforces a nondeterministic ordering of ids to produce a state transition. this is fine from a minimalist standpoint. a deterministic ordering can be influenced as I understand it via dependency (require/watch/etc) predicates or an explicit ordering (order) parameter. If I understand the ordering however, all IDs that resolve to the same order can then again fall into a nondeterministic situation as well. As for how order and predicates interact I know not nor have tested.

N=2 id scenario, given N=2 different IDs trying to accomplish a state transition
- id A
- id B
- no explicit relationship exists between A and B in any state file
- A and B have an implicit relationship such that B requires A, external to salt (config file assumption, package dependency, etc)

2 ids to resolve means (2!)=2 solutions exist:

production option 1)
highstate `#1` for this state will complete A, then B, all is well.

production option 2)
highstate `#1` for this state will fail on B, then complete A. highstate `#2` for this state will complete B, then pass on A, already being done.

N>2 IDs produces far more permutations and would require worst case N! highstate invocations to progress from state.before_tried to state.after_realized. this happens because in scenario `#2`, the call to highstate can partially succeed.

What worse is that some step K in a production may only be allowed to run once or is in some other manner non-idempotent (like generate a ssl csr or something) so subsequent highstate invocations may never be able to reach the intended state.

The typical solution is to bring the external dependency into salt as a predicate to ensure the ->A,B production of the state. Currently this is the solution I am using and that is fine for myself as I can figure out the predicates manually. However, random users may have no idea how to extrapolate that dependency for system packages or the like.

The question becomes, is that an accepted limitation of salt, or do we want transaction states too?

Should a state that require N IDs, and 0..M `(M0Σ ` i.undo inversions to bring the state back to where it was prior to the new state failure. Whether the absent/present function can satisify such inversions is another issue.

Without such guarantees on state transitions it is extremely difficult to achieve complex arbitrary convolutions. Is there an arbitrary way to confirm a given state is fully deployed?