Skip to content

Changelog

All notable changes to this project are documented here. Format follows Keep a Changelog, and this project adheres to Semantic Versioning.

[0.6.0] - 2026-09-03

Added

  • client.clusters.resolve(name): look up a cluster by name, symmetric to client.nodes.resolve().
  • client.applications.default_services(app_version): builds the (compose_config, app_secrets) a fresh Marketplace/Model workload needs from a published app version's template, decoding its base64 defaults — avoids reimplementing this per caller.

Fixed

  • client.clusters.workloads.create_marketplace_workload/create_model_workload (and their update_* counterparts) now raise a clear ValueError when deployment/placement_constraints reference a service name absent from compose_config/app_secrets, instead of silently adding an extra service and letting the API reject the whole request with a length-mismatch 400.

[0.5.0] - 2026-08-08

First public release.

Added

  • BarbaraClient and AsyncBarbaraClient, with OAuth2 password-grant authentication, automatic token refresh, and a single automatic retry on a 401 with a fresh token.
  • Optional http2=True (requires the barbara-api-sdk[http2] extra) — mainly useful for AsyncBarbaraClient under asyncio.gather, multiplexing many concurrent requests over one connection.
  • Optional max_retries (default 0): retries a connection error or a 429/502/503/504 response with exponential backoff, honoring a 429's Retry-After header. A retried request whose body streams from an open file is rewound before resending, so a partially-sent multipart upload is never silently truncated.
  • client.settings (ClientSettings): a read-only snapshot of a client's own transport configuration (timeout/http2/max_retries), separate from client.config (credentials and URLs).
  • client.nodes: lifecycle (list, paginate, get, resolve, delete, add_node), identity (name, tags, location, safety actions, groups), Global Secrets, Global Config, docker credentials, actions (reboot, poweroff, provision, deprovision, brick), Node Assets, Barbara Core updates, docker maintenance and volumes, and telemetry. list_by_tags selects every node carrying at least one of a given set of tags — a client-side convenience, since the wire's list endpoint has no server-side tag filter.
  • client.nodes.network: the Networking card — physical interfaces (Ethernet, WiFi, Mobile), VLANs, hostname, VPN, Proxy, Standalone Mode, IPTables, and NTP servers. Every write is checked (best-effort, non-blocking) against the caller's token role before being sent.
  • client.nodes.workloads: Docker, Marketplace, and Model workloads on a single node — create, update, start, stop, delete, logs, container info, running-service detail, command-result history and pending-action state, and each workload type's own configuration surface:
  • Docker: App Config only.
  • Model: Compose Config only (compose_config: ports/volumes per service).
  • Marketplace: App Config, Compose Config, and App Secrets (app_secrets: per-service environment variables, readable back unlike Global Secrets). Partial updates to just Compose Config or just App Secrets preserve whichever side isn't being changed.
  • A deployed Marketplace app's published URLs are available through get_urls.
  • client.clusters: lifecycle (list, paginate, get, create, update, delete), node membership (join, leave, pause, drain, set active, update config), Global Secrets, Global Config, docker credentials, and Swarm-managed docker volumes.
  • client.clusters.workloads: the cluster-level equivalent of client.nodes.workloads — the same Docker/Marketplace/Model configuration surface deployed across every node in a cluster at once, plus two configuration axes that only apply at cluster scope: Deployment & Replicas (deployment: mode/replicas per service) and Placement Constraints (placement_constraints: tag-based {tag: value} per service, pinning a service to matching nodes). get_urls and running-service detail are available by reading the cluster's own current state.
  • client.applications: application and application version CRUD, with streamed multipart/form-data file uploads (icon, installable artifact) and a per-call timeout= override for large uploads.
  • client.models: model and model version CRUD, with the same streamed multipart uploads; a version's sha256/size are computed automatically from the artifact.
  • client.configs: the Config Repository — reusable, named configuration documents (typed application or global), referenced by id from a node's/cluster's Global Config or a workload's App Config.
  • client.groups: node group CRUD.
  • client.users: read-only user listing and pagination, with User.role typed as UserRole (ADMINISTRATOR/SUPERVISOR/EDITOR/VIEWER).
  • client.alerts: alert listing, acknowledgement, and alert events.
  • client.api_version().
  • Typed exceptions: BarbaraApiError, BarbaraAuthError, BarbaraNotFoundError, BarbaraPermissionError.
  • Full sync and async test coverage using respx HTTP mocking.
  • Generated API reference documentation site, built from docstrings with mkdocs + mkdocstrings and published to GitHub Pages.
  • Every id passed to a resource method (node id, workload id, cluster id, ...) is percent-encoded before being placed in a request path, so a value containing /, ?, or other URL-structural characters can't redirect a call to an unintended endpoint or inject query parameters.
  • TLS certificate verification is on by default; disabling it (verify_tls=False / BBR_VERIFY_TLS=false) emits a runtime warning.
  • BarbaraConfig and the internal token object exclude client_secret, password, and the access token from their repr(), so they can't end up in a log line or traceback by accident.
  • File uploads (application/model icons and artifacts) stream from disk instead of loading the whole file into memory, so a multi-gigabyte artifact doesn't have to fit in the client process's RAM.
  • CI and release workflows pin every third-party GitHub Action to a commit SHA and request only the permissions each job needs.
  • A dedicated security workflow runs static analysis (bandit) and a dependency vulnerability scan (pip-audit) on every push, pull request, and release, and gates PyPI publishing on both passing.
  • Response fields are typed to match what the API actually returns, including cases where the wire value is an object rather than a plain scalar (Node.status, Alert.severity, AlertEvent.event_type) or a nested reference object rather than a plain id (Alert.node_id, AlertEvent.node_id/alert_id, Group.node_ids).
  • Every release is gated on a full read+write lifecycle test (nodes, the applications/models catalog, workloads, Barbara Core update scheduling) against a real Barbara environment. A separate daily, read-only check verifies the live API still matches what this SDK's typed models expect, so an incompatible API change is caught early.

Known issues

  • client.nodes.set_location currently returns a 500 Internal Server Error for any payload. Use the Panel to update a node's location until this is resolved.
  • client.nodes.network.create_ntp_server doesn't return the created entry's id, and there is no GET/list endpoint for NTP servers. Read the current list, including each entry's id, from client.nodes.get(node_id).raw["deviceConfig"]["ntpServers"] instead.