Reconciliation Loop#

Reconciliation loop re-executes the states until all states are successfully realized or no progress is made.

Reconciler Plugin#

The reconciler plugin provided by idem is called ‘basic’. Idem reconciliation loop will re-apply pending states. It stops if none of the states is “pending” or if results/changes have not changed during the last 3 iterations.

Loop Implementation#

To implement a reconciler plugin, provide a method like this:

from typing import Dict, Any

async def loop(
    hub,
    pending_plugin; str,
    name: str,
    apply_kwargs: Dict[str, Any],
    ):
    ...

The reconciler loop should return a dictionary like this:

{
    "re_runs_count": <number reconciliation loop iterations>,
    "require_re_run": <True or False>,
}

Reconciliation Wait Time#

Reconciliation wait time is the sleep time between loop iteration. Each state can define a separate reconciliation wait time in seconds. For each iteration of the reconciliation loop, the wait time is re-calculated for the pending states, and the longest wait time value is used. By default, the idem reconciler plugin uses 3 seconds wait time unless defined by the state.

Idem supports three algorithms for calculating the wait time:
  • static

  • random

  • exponential

Static#

Fixed wait time value defined on the state, which remains the same for all iterations. For example:

__reconcile_wait__ = {"static": {"wait_in_seconds": 10}}

The default value is static of 3 seconds.

Random#

Random wait time expects minimum and maximum values and generates a random number in that range (inclusive). It is defined in the state like this:

__reconcile_wait__ = {"random": {"min_value": 1, "max_value": 10}}

In this example, a random number from 1 to 10 is generated before each reconciliation iteration.

Exponential#

A wait time that increases for every reconciliation iteration. The exponential wait time is calculated based on this formula:

wait_in_seconds * (multiplier ^ run_count)

Where ‘run_count’ is the number of the iteration. The default value is 0. For example:

__reconcile_wait__ = {"exponential": {"wait_in_seconds": 2, "multiplier": 10}}

In the example, exponential wait times are: 2, 20, 200…

Pending plugin#

Pending plugin is used to determine whether a state is in a “pending” state that requires reconciliation, which would re-apply the state.

To implement a pending plugin, provide a method like this:

def is_pending(hub, ret):

is_pending returns True if more reconciliation is needed, otherwise False.

The default implementation is defined in default.py, and returns False if ‘result=True’ and there are no ‘changes’, where ‘changes’ is the delta between the previous state and the required state.

CLI#

The reconciler plugin and pending plugin are specified as an argument to the idem state CLI.

For example:

--reconciler=basic | -R=basic | -r=basic
--pending=default | -P=default | ip=default

Reconciliation loop is enabled by default, to disable it use –reconciler=none.

Batch Function#

Reconciliation loop can also be run in a batch command. For example:

hub.pop.Loop.run_until_complete(
    hub.idem.state.batch(
        states=states,
        name=name,
        runtime="serial",
        renderer="json",
        test=False,
        encrypted_profiles=encrypted_profiles,
        acct_key=acct_key,
        default_acct_profile="default",
        reconcile_plugin="basic",
        pending_plugin="default",
    )
)

Notes#

  • There is no reconciliation for exec commands (exec.run) that are successful.

  • There is no reconciliation during ‘test’ invocations (–test=True).