Skip to content

plexctl blueprint

Synopsis

plexctl blueprint is the operator surface for the Blueprint Catalog. The read subcommands inspect the catalog; the authorship subcommands register a Blueprint and publish immutable versions under it on /v1/blueprints.

text
plexctl blueprint <subcommand> [flags]

Subcommands

plexctl blueprint list

GETs /v1/blueprints. Pagination is keyset-based via --cursor / --limit; the --all flag follows next_cursor until exhausted (mutually exclusive with --cursor).

With --project <uuid> the command GETs /v1/projects/{id}/blueprints instead: the same catalog, with a PROVISIONABLE column saying whether that Project can provision each Blueprint today and a PROVIDER_KINDS column naming the substrates the Blueprint's published versions accept. A leading REACHABLE_PROVIDER_KINDS line names the substrates the Project reaches through its approved Cloud Assignments, and reads none when it reaches nothing. Read against each other, the two answer which Cloud a non-provisionable Blueprint is waiting on. Malformed --project values are rejected locally before the wire. --limit, --cursor and --all work the same way against the nested endpoint; --output json and --output yaml render the raw response, which carries both kind sets.

plexctl blueprint get <id>

GETs /v1/blueprints/{id}. Local UUID validation rejects malformed id with exit 2 before the wire. The text render includes the embedded versions array and, for each version, the typed parameter_schema rows.

plexctl blueprint create

POSTs /v1/blueprints to register a new catalog entry. The call is gated by the platform-level manage relation (platform#manage); a caller without it receives a 403 (exit 4). A duplicate --slug surfaces as 409 blueprint_slug_conflict (exit 1). On success the registrar is granted owner on the new Blueprint, which confers publish — the grant is written asynchronously, so a version create issued in the same instant may be refused until it propagates.

plexctl blueprint version create

POSTs /v1/blueprints/{id}/versions to publish an immutable version under an existing Blueprint, gated by the Blueprint's publish permission (blueprint#publish). The XRD, Composition, and parameter-schema documents are read from JSON files. A duplicate --version surfaces as 409 blueprint_version_exists; a malformed manifest pair as 400 invalid_manifest; an out-of-set provider kind or injection strategy as 400 invalid_provider_kind / 400 invalid_injection_strategy.

plexctl blueprint catalog add

POSTs /v1/blueprint-catalogs to register an external OCI catalog source. Exactly one of --ref (tag-pinned, e.g. ghcr.io/org/catalog:v1.2.3) or --digest (digest-pinned, e.g. ghcr.io/org/catalog@sha256:…) names the bundle. The verification policy is either a pinned cosign identity (--verify-identity with --verify-issuer) or --insecure-unsigned; one of the two must be chosen. --track turns on tag re-resolution at the given interval (pinned when omitted). --domain-id scopes the source to a single Domain (catalog-global when omitted), which selects the relation the call is gated on (domain#manage versus platform#manage). A malformed reference is rejected locally with exit 2; the server is the authority on reference validity and returns 400 invalid_oci_reference, 400 invalid_verification_policy, or 400 invalid_tracking_policy for a policy it rejects.

plexctl blueprint catalog list

GETs /v1/blueprint-catalogs. The source set is small, operator-curated configuration returned whole, so the command carries no pagination flags; items is the subset the caller is authorised to see.

plexctl blueprint catalog get <id>

GETs /v1/blueprint-catalogs/{id}. Local UUID validation rejects a malformed id with exit 2 before the wire.

plexctl blueprint catalog rm <id>

DELETEs /v1/blueprint-catalogs/{id} to deregister a source. The operation is destructive and refuses to run without the root --yes flag. A 204 confirms removal.

plexctl blueprint catalog browse <id>

GETs /v1/blueprint-catalogs/{id}/blueprints to list the Blueprints a source's bundle offers. Nothing is imported — the response carries the bundle metadata (slug, display name, version, provider kinds, injection strategy) only.

plexctl blueprint import <catalog-id> [slug...]

POSTs /v1/blueprint-catalogs/{id}/import to import Blueprints from a registered source. Supply either an explicit list of slugs or --all to import every Blueprint the source offers; supplying neither or both is rejected locally with exit 2. Drift and conflict are reported per-Blueprint in the outcomes, not as a batch failure, so the command exits 0 and renders one row per requested slug.

Flags

plexctl blueprint list

FlagTypeRequiredDescription
--limitintnoMaximum items per page (server default when zero).
--cursorstringnoContinuation token from a previous call.
--allboolnoFollow next_cursor until exhausted. Mutually exclusive with --cursor.
--projectstring (uuid)noRead the catalog through one Project: adds the PROVISIONABLE verdict and the reachable-provider line. Malformed values fail before the request.

plexctl blueprint create

FlagTypeRequiredDescription
--slugstringyesKebab-case catalog handle, unique across the catalog.
--display-namestringyesHuman-readable Blueprint name.
--descriptionstringnoFree-form description.
--domain-idstringnoOwning Domain UUID; catalogue-wide when omitted.

plexctl blueprint version create

FlagTypeRequiredDescription
--blueprint-idstringyesParent Blueprint UUID.
--versionstringyesVersion label, unique within the Blueprint.
--injection-strategystringyesOne of cloud-init-user-data, helm-values, provider-secret.
--provider-kindsstringsyesComma-separated subset of aws, azure, gcp, hetzner, openstack.
--xrd-filestringyesPath to the Crossplane XRD manifest as a JSON file.
--composition-filestringyesPath to the Crossplane Composition manifest as a JSON file.
--parameter-schema-filestringyesPath to the parameter-schema document as a JSON file ({"parameters":[...]}).

plexctl blueprint catalog add

FlagTypeRequiredDescription
--namestringyesHuman-facing label for the source.
--refstringone of --ref/--digestTag-pinned OCI reference (registry/repository:tag).
--digeststringone of --ref/--digestDigest-pinned OCI reference (registry/repository@sha256:…).
--verify-identitystringwith --verify-issuerCosign signing-identity SAN regexp (pinned verification).
--verify-issuerstringwith --verify-identityExpected OIDC issuer (pinned verification).
--insecure-unsignedboolone mode requiredAccept the bundle without signature verification. Mutually exclusive with the verify flags.
--trackdurationnoRe-resolve the source's tag on this interval (track-tag); pinned when zero.
--domain-idstringnoOwning Domain UUID; catalog-global when omitted.
--registry-credential-refstringnonamespace/name of the registry-credential Secret.

plexctl blueprint catalog rm

FlagTypeRequiredDescription
--yesboolyesConfirm the destructive deregistration (inherited from root).

plexctl blueprint import

FlagTypeRequiredDescription
--allboolone of --all/slugsImport every Blueprint the source offers. Mutually exclusive with explicit slugs.

Persistent flags inherited from root

--server, --profile, --token-file, --output. See ../plexctl.md.

Exit codes

See ../plexctl.md#exit-code-taxonomy.

Examples

List all Blueprints across pages

shell
plexctl blueprint list \
  --server "${PLEXSPHERE_URL}" \
  --all    \
  --output json

See which Blueprints a Project can provision

shell
plexctl blueprint list \
  --server "${PLEXSPHERE_URL}" \
  --project 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0aa
text
REACHABLE_PROVIDER_KINDS: aws
SLUG              NAME               STATUS  PROVIDER_KINDS  PROVISIONABLE
managed-postgres  Managed PostgreSQL active  aws             yes
managed-bigquery  Managed BigQuery   active  gcp             no

The second row needs a gcp Cloud, and the Project reaches only aws. Request one with plexctl cloud assignment request and it becomes provisionable once an operator approves it.

Inspect a single Blueprint

shell
plexctl blueprint get 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0b0 \
  --server "${PLEXSPHERE_URL}" \
  --output yaml

Register a Blueprint

shell
plexctl blueprint create \
  --server "${PLEXSPHERE_URL}" \
  --slug managed-postgres \
  --display-name "Managed PostgreSQL" \
  --description "A managed PostgreSQL database instance."

Publish a version

shell
plexctl blueprint version create \
  --server "${PLEXSPHERE_URL}" \
  --blueprint-id 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0b0 \
  --version 1.0.0 \
  --injection-strategy helm-values \
  --provider-kinds aws,hetzner \
  --xrd-file ./xrd.json \
  --composition-file ./composition.json \
  --parameter-schema-file ./parameter-schema.json

Register a catalog source with a pinned signing identity

shell
plexctl blueprint catalog add \
  --server "${PLEXSPHERE_URL}" \
  --name "Platform catalog" \
  --ref ghcr.io/plexsphere/catalog:v1.2.3 \
  --verify-identity '^https://github\.com/plexsphere/.*$' \
  --verify-issuer https://token.actions.githubusercontent.com

Browse the Blueprints a source offers

shell
plexctl blueprint catalog browse 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0e1 \
  --server "${PLEXSPHERE_URL}"

Import every Blueprint a source offers

shell
plexctl blueprint import 0190a8b8-a0c0-7a0a-8a0a-a0a0a0a0a0e1 \
  --server "${PLEXSPHERE_URL}" \
  --all

Cross-references