Skip to main content

Example: deploy a Marketplace app to a cluster

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

Overview

deploy_marketplace_cluster.py is the cluster-scope counterpart to Deploy Marketplace app (node): it resolves a cluster by name, resolves the application and version the same way, and creates a Marketplace stack replicated across the cluster's nodes.

It adds the two configuration axes that only exist at cluster scope: --deployment sets each service's Deployment & Replicas mode, and --placement pins a service to nodes carrying matching tags (Placement Constraints). Everything else, including how overrides are given, matches the node-scope script.

Get the script

Download deploy_marketplace_cluster.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_cluster() looks the cluster up by name unless the argument already looks like an internal _id:

def resolve_cluster(client: BarbaraClient, identifier: str) -> Cluster:
if INTERNAL_ID_RE.match(identifier):
return client.clusters.get(identifier)
return client.clusters.resolve(identifier)

client.clusters.resolve(name) is the cluster-scope counterpart to client.nodes.resolve(): useful when a script only has the cluster's human-readable name rather than its internal _id.

The application, version, and default services resolve exactly as in the node-scope script, via client.applications.list_versions and client.applications.default_services. --compose-config-file/--app-secrets-file/--app-config-file overrides work the same way too, see Deploy Marketplace app (node) for that part in depth.

parse_deployment() turns repeated --deployment service:mode[:replicas] flags into the SDK's deployment shape, one entry per service, validating locally before any call is made:

_DEPLOYMENT_MODES = {"replicated", "global", "replicated-job", "global-job"}

replicas is required for the replicated/replicated-job modes and rejected for the others, matching the API's own rule. parse_placement() turns repeated --placement service:tag=value flags into placement_constraints, grouping multiple tags for the same service into one constraints dict.

Both parsers check each service name against the app version's template first:

if name not in known_names:
raise SystemExit(
f"{flag} '{raw}': '{name}' is not a service in the app version's "
f"template. Available: {', '.join(known_names)}"
)

A --deployment/--placement service name has to be the marketplace template's own service name (for example socat), not the deployed stack's display name. Left unchecked, a typo here would silently add an extra service to the request instead of erroring, and the API would then reject the whole call with a length-mismatch 400; catching it locally gives a clear error message instead.

Run it

# Read-only: print the deployment plan (resolved application/version, default services).
python deploy_marketplace_cluster.py "Production Cluster" --app Grafana

# Deploy a specific version, replicated 3x and pinned to a zone.
python deploy_marketplace_cluster.py "Production Cluster" --app Grafana --version 10.3.3-b.7 \
--deployment grafana:replicated:3 --placement grafana:zone=eu-west --apply

Try it

Run it without --apply first and check the resolved application_id/app_version_id match what Panel shows for that app. Pass a --deployment/--placement service name that isn't in the app version's template and see the resulting error, caught locally before any call is made. After deploying, check client.clusters.workloads.get_running_services(...) to see the live Docker Swarm service state once the stack comes up.

Extend it

  • Deploy to both scopes from one script. Use this script alongside Deploy Marketplace app (node) for the node-scope counterpart.
  • Replicate a live stack instead of the template. Look up an already-deployed stack's current services instead of starting from default_services, the same idea as the node-scope script's equivalent extension.

Summary

You resolved a cluster and a Marketplace application version by name, built the deployment's Compose Config/App Secrets from the version's own published template, added Deployment & Replicas and Placement Constraints for the services that need them, and deployed the stack, with a safe read-only plan by default.

The same template-first approach that avoids length-mismatch errors at node scope applies here too: client.clusters.resolve and client.applications.default_services remove two of the most error-prone steps of a cluster deployment script.

For the full deploy flow, see Marketplace workload deployment and Clusters & cluster workloads. For the full method list, see client.clusters and client.clusters.workloads in the Reference.