Skip to content
🛡️ adminadmin@example.com · Domain admin in Acme Corp

Chapter 10 — Provision a Resource ​

Everything the broker needs is now in the shell ​

A Project. An approved credential. A blueprint version.

bash
RESOURCE_ID=$(plexctl resource create \
  --project-id "$PROJECT_ID" \
  --kind bucket \
  --blueprint-version-id "$BLUEPRINT_VERSION_ID" \
  --cloud-credential-id "$CREDENTIAL_ID" \
  --parameters '{"region":"us-east-1"}' \
  --output json | jq -r '.id')
echo "$RESOURCE_ID"

The Blueprint declares region as required. Omit it and the call fails closed — before any substrate is touched.

Accepted, not done ​

bash
plexctl resource get "$RESOURCE_ID" --output json | jq '{kind, origin, phase: .provisioning.phase}'
json
{
  "kind": "bucket",
  "origin": "provisioned",
  "phase": "Pending"
}

resource create returned 202 Accepted. Provisioning is asynchronous — the call accepted your declaration.

From here you do nothing. A reconcile loop drives it forward.

Watch it move ​

bash
plexctl resource get "$RESOURCE_ID" --output json | jq -r '.provisioning.phase'
bash
while true; do
  PHASE=$(plexctl resource get "$RESOURCE_ID" --output json | jq -r '.provisioning.phase')
  echo "$(date +%T) $PHASE"
  case "$PHASE" in Ready|Failed) break ;; esac
  sleep 10
done
text
14:31:02 Pending
14:31:12 Provisioning
14:33:12 Ready

Presenter note: this is up to two minutes of dead air. Use it — the next slide explains what each transition actually observed.

Each phase is an observation, never a timer ​

Pending → Provisioning — the Project's management-fleet namespace became ready, so the broker applied the Blueprint's composite resource. No bootstrap token is minted: there is no node to enrol.

Provisioning → Ready — the AWS provider composed the bucket against the emulated endpoint and Crossplane reported the substrate ready.

A standalone resource has only these two transitions. It skips the enrolment phase entirely, because nothing registers back.

Does the bucket actually exist ​

bash
kubectl run floci-probe --rm -i --quiet --restart=Never \
  --image=curlimages/curl:8.10.1 -- -sS http://floci:4566/ \
  | grep -o '<Name>[^<]*' | cut -d'>' -f2
text
pr-019fb9d7-fb6c-7681-a082-07407e041cc0-a2908b4cb3ce

Not a status field the platform set about itself — the object, listed out of the emulated AWS, its name derived from the Resource id.

This is the whole point of the last three chapters. The catalog, the approval, and the credential all existed so that this bucket could be created by somebody who never held a cloud key.

And take it away again ​

bash
plexctl resource delete "$RESOURCE_ID" --yes
bash
while true; do
  PHASE=$(plexctl resource get "$RESOURCE_ID" --output json | jq -r '.provisioning.phase')
  echo "$(date +%T) $PHASE"
  case "$PHASE" in Deleted|Failed) break ;; esac
  sleep 10
done

Deprovisioning is the same machinery in reverse, and it is observed the same way — Deleted means the substrate confirmed it, not that the platform gave up waiting.

Presenter note: optional. If time is short, delete and move on without watching — chapter 11 provisions something more interesting anyway.