Skip to lesson
Exit
Automation, IaC & Zero-Trust Engineering1 / 3

1 min lesson

Production automation, four attributes

Use "Production automation, four attributes" to explain each part and the role it plays.

Step 1 of 3

The four properties graders look forwhat separates a script from a toy

Production automation, four attributes
Idempotent
Running it twice produces the same end state - you check-then-act, never blind-create
Resilient
Pagination, retries with backoff on 429/5xx, timeouts and a clear failure path
Observable
Structured logs, a summary of what changed and an alert when a run fails
Safe
A --dry-run that prints the diff without mutating and secrets pulled from a vault not the source

If you can name these four and show them in code, you've cleared most of the scripting screen before writing a single helper.

Learn more

Full explanation

Talk to a SaaS API the way the API expects

Talk to a SaaS API the way the API expectsOkta, Google, Slack all bite the same way

Every IT-facing API has the same three traps: it pages its results, it rate-limits you and it occasionally 500s mid-batch. A senior answer wires all three into a small reusable client rather than copy-pasting requests.get everywhere.

Idempotent Okta group-membership sync with paging + retry/backoff
import os, time, logging, requests

OKTA = os.environ["OKTA_ORG_URL"]            # injected, never hard-coded
TOKEN = os.environ["OKTA_API_TOKEN"]         # from the secrets manager
S = requests.Session()
S.headers.update({"Authorization": f"SSWS {TOKEN}"})
log = logging.getLogger("jml")

def get_all(path):
    """Follow Okta's Link: rel=next paging, retry on 429/5xx."""
    url, out = f"{OKTA}{path}", []
    while url:
        for attempt in range(5):
            r = S.get(url, timeout=30)
            if r.status_code == 429 or r.status_code >= 500:
                wait = int(r.headers.get("Retry-After", 2 ** attempt))
                log.warning("throttled, sleeping %ss", wait); time.sleep(wait); continue
            r.raise_for_status(); break
        else:
            raise RuntimeError(f"gave up on {url}")
        out += r.json()
        url = r.links.get("next", {}).get("url")
    return out

def converge_membership(group_id, desired_ids, dry_run=True):
    current = {u["id"] for u in get_all(f"/api/v1/groups/{group_id}/users")}
    add, remove = desired_ids - current, current - desired_ids
    log.info("group %s: +%d -%d", group_id, len(add), len(remove))
    if dry_run:
        return {"add": sorted(add), "remove": sorted(remove)}   # show the diff, change nothing
    for uid in add:
        S.put(f"{OKTA}/api/v1/groups/{group_id}/users/{uid}", timeout=30).raise_for_status()
    for uid in remove:
        S.delete(f"{OKTA}/api/v1/groups/{group_id}/users/{uid}", timeout=30).raise_for_status()
    return {"added": len(add), "removed": len(remove)}

Notice the shape: read the current state, compute a diff against desired and apply only the delta. That's a reconcile-and-converge loop and it's idempotent for free because a second run finds nothing to change.