Skip to main content

Example: check Barbara Core updates

This article refers to SDK version v0.5.0. The current SDK version is N/A.

Overview

check_barbara_core_updates.py checks a fleet for an outdated Barbara Core, the single versioned package that bundles a node's OS and Node Manager together (for example Barbara Core 1.10.1.471, matching the single version number Panel's own update modal shows), and optionally rolls out the update. It's the kind of check you'd run on a schedule, a cron job or a CI pipeline, to catch drift before it becomes a problem.

Like the other scripts that can modify data, it defaults to a dry run: it prints what it would do and changes nothing until you pass --apply.

Get the script

Download check_barbara_core_updates.py from the SDK's examples/ directory. If you haven't installed the SDK yet, see Getting started.

Set up credentials

The script reads the four Barbara API Credentials from environment variables, or from a .env file placed next to it (loaded automatically, or pointed at with --env-file). See Set up credentials in the Hello World walkthrough for the full picture.

Walk through the code

resolve_node() accepts either an internal _id or a Barbara ID, the same dual lookup used by the node info example.

all_nodes() pages through every node in the company, since a plain list() call only returns a single page:

def all_nodes(client: BarbaraClient) -> list[Node]:
nodes: list[Node] = []
offset = 0
size = 100
while True:
page = client.nodes.paginate(size=size, from_=offset)
nodes.extend(page.items)
if not page.items or page.total is None or len(nodes) >= page.total:
break
offset += size
return nodes

It's used when no specific nodes are given on the command line, see client.nodes.paginate in the Reference for the underlying method.

evaluate_node() derives Barbara Core status from the node's raw payload, since it isn't on the typed Node model yet:

version = node.raw.get("deviceVersion") or {}
last = version.get("lastVersion") or {}
needs_update = bool(last.get("updateAvailable"))

deviceVersion.lastVersion.updateAvailable covers the OS and Node Manager together, what the API and Panel both surface as a single "Barbara Core" version. evaluate_node also reports the current vs. latest version for both the OS and the agent separately, so the output tells you not just that a node is behind, but by how much.

send_update() sends the update:

def send_update(client: BarbaraClient, node_id: str) -> None:
client.nodes.update_barbara_core(node_id, "update")

update_barbara_core(node_id, update_type) is the same resource method Panel's own Barbara Core Update button calls. Sending update_type="update" takes no other body: the node pulls whatever it currently reports as the latest version.

main() ties it together: evaluate every targeted node, and for each one that needs an update, either report "dry-run" (no --apply) or actually call send_update and report "updated" or "error". At the end, it exits with status code 1 if any update failed, which is what makes the script safe to wire into a CI step or an alert:

if any(r["status"] == "error" for r in results):
raise SystemExit(1)

Run it

# Read-only: report which nodes need an update, across your whole fleet.
python check_barbara_core_updates.py

# Only these nodes.
python check_barbara_core_updates.py node-01 node-02 node-03

# Send the update to every node that needs one (whole fleet, or the ones listed).
python check_barbara_core_updates.py --apply
Preview before you apply

Always run without --apply first and read the plan before sending anything.

Try it

Run it without --apply and read the printed plan: needsUpdate, plus current vs. latest OS and agent version, per node. Then check the exit code with echo $?, 0 if nothing failed, 1 if any update errored, and picture wiring that into a CI step or an alert. If you manage a large fleet, watch all_nodes() page through client.nodes.paginate(...) instead of a single list() call, that's the difference that matters once your company has more nodes than fit on one page.

Extend it

  • Target a group instead of the whole company. Resolve client.groups.get(group_id).node_ids first, then evaluate just those nodes instead of every node you manage.
  • Add concurrency. For a large fleet, evaluate and update nodes in parallel, a thread pool, or asyncio.gather with AsyncBarbaraClient, bounded by a timeout so one unresponsive node doesn't block the whole batch.
  • Alert instead of print. On a send_update failure, raise a Barbara alert or post to a webhook instead of just recording status: "error" in the output.

Summary

You audited a fleet for an outdated Barbara Core and, optionally, rolled out the update, with a dry run by default and an exit code that tells a script or a pipeline whether anything went wrong.

That dry-run-by-default, exit-code-on-failure shape is worth reusing: it's what makes a script safe to run unattended on a schedule.

For a similar fleet-wide audit, this time of a node's network configuration, continue to Network audit. For the full method list, see client.nodes in the Reference.