Skip to content

Check mode, diff and idempotency

Every module in the collection supports --check for real, and write modules report changed truthfully from a fetch-compare-write cycle. This was the headline fix of v2: the v1 update modules declared check-mode support but performed live writes during --check. If you automate against a production NetOrca, this page is the contract you can rely on.

What check mode means, per module class

Module class In check mode changed
*_info runs normally (it is read-only anyway) always false
write modules fetches current state, validates the request, returns the projected result and diff - sends no mutating request what would change
$ ansible-playbook fulfilment.yml --check --diff
TASK [Complete the change] *****************************************************
changed: [localhost] => {"changed": true, "msg": "state APPROVED -> COMPLETED", ...}
--- before
+++ after
 {
-    "state": "APPROVED"
+    "state": "COMPLETED"
 }

Because validation happens client-side before the write, check mode also catches illegal state transitions and missing targets - a dry run is a genuine preflight.

Idempotency

Write modules are desired-state, not imperative:

  • netorca_change_instance with state: COMPLETED on an already-completed change (same log, same deployed item) sends nothing and reports changed: false.
  • netorca_deployed_item deep-compares data and skips identical updates.
  • Re-running a fulfilment playbook is safe by design: the work queue is the state, so a crashed run's leftovers are simply picked up next time. The scenarios lean on this.

The change instance state machine

The platform enforces a strict lifecycle. The module validates transitions client-side first, so an illegal request fails instantly with the legal options listed - not with an opaque API error.

stateDiagram-v2
    [*] --> PENDING: consumer submits
    PENDING --> APPROVED: validation passed
    PENDING --> REJECTED: validation failed (log says why)
    REJECTED --> PENDING: consumer resubmits / re-open
    APPROVED --> COMPLETED: deployed (attach deployed_item)
    APPROVED --> ERROR: deployment failed (log says why)
    PENDING --> CLOSED
    APPROVED --> CLOSED
    REJECTED --> CLOSED
    ERROR --> CLOSED
    COMPLETED --> [*]
    CLOSED --> [*]
To ↓ Legal from
APPROVED PENDING
REJECTED PENDING
PENDING REJECTED
COMPLETED APPROVED
ERROR APPROVED
CLOSED PENDING, APPROVED, REJECTED, ERROR

An illegal request fails like this (before any API call):

fatal: [localhost]: FAILED! => {"current_state": "COMPLETED", "msg": "Illegal change
instance transition COMPLETED -> APPROVED. Legal target states from COMPLETED: none."}

One often-confused nuance: the service's allow_manual_approval / allow_manual_completion flags govern GUI (human) approvals only - API transitions like this module's are always available to the owning team (details).

Diff mode

Write modules return diff with before/after limited to the fields actually being changed - usable with --diff on the CLI and in callbacks. Check mode and diff compose: --check --diff is a full preview of a fulfilment run.

Try it safely

guardrails_demo.yml exercises the guardrails on purpose against a live instance without writing anything, and the read-only smoke suite runs the write modules in check mode as part of CI's integration stage.