Skip to content

feat(resmgr): pcd_cluster_blueprint resource (write path) — validated live - #33

Merged
PF9-pushkar merged 1 commit into
mainfrom
feat/blueprint-resource
Jul 14, 2026
Merged

feat(resmgr): pcd_cluster_blueprint resource (write path) — validated live#33
PF9-pushkar merged 1 commit into
mainfrom
feat/blueprint-resource

Conversation

@PF9-pushkar

Copy link
Copy Markdown
Collaborator

Adds the pcd_cluster_blueprint resource, and supersedes the earlier "not viable" decision (#32).

Why the earlier call was wrong

That conclusion — "blueprint update has no working path" — was an artifact of the single-blueprint CE lab. PCD supports one blueprint per region; my earlier update test had created a second blueprint (a state PCD doesn't support), whose PUT /blueprint/{name} then 404'd. Against a demo env with a single real blueprint (cluster-1), the write path works — verified end-to-end through the provider:

  • terraform import cluster-1clean plan (round-trip correct)
  • in-place apply changing dns_domain_name0 added, 1 changed, 0 destroyed, confirmed via the API
  • reverted, then state rm (detached, not deleted). cluster-1 restored to its original state.

Design

The write API requires the whole object, so all attributes are Optional+Computed and the full object is sent on every write. After a write, state keeps the user-configured (known) plan values and refreshes only unknowns from the server — so the server's re-serialization/normalization of a configured attribute can't trip "inconsistent result after apply".

  • storage_backends_json is Sensitive (plaintext driver credentials), required on create (PCD 500s a blueprint with no backends), and read back so writes preserve the current backends unless changed.
  • Delete is a no-op that only removes the resource from Terraform state — a region singleton is normally imported, so destroy should stop managing it, not delete the cluster-defining blueprint every host/cluster depends on.
  • name is ForceNew.

Adversarial review — 6 findings, all fixed

A per-lens review workflow (state-consistency / REST-API / lifecycle, each verified against framework + gophercloud source) found 6 issues, all fixed and re-validated live:

  1. (HIGH) storage_backends_json round-trip → "inconsistent result after apply" when set → keep the known plan value. Re-tested with it set: apply succeeds, plan clean.
  2. (MEDIUM) wholesale re-GET clobbered all known plan values → same "keep known, refresh unknowns" fix.
  3. (LOW) three bools lacked UseStateForUnknown → added.
  4. (HIGH) Create could orphan on read-back failure → warn (not error), keep state.
  5. (MEDIUM) Update hard-errored on read-back failure → warn, persist plan.
  6. (LOW) destroy deleted the region singleton → made Delete a no-op detach + documented.

Testing

build / vet / gofmt / golangci-lint (0) / unit tests / terraform fmt / docs — all clean. Mutating acc tests stay opt-in (PCD_ACC_RESMGR); the resource was validated manually against the demo env (safely, via import + in-place update + revert + state rm, never destroy).

Supersedes the earlier "not viable" call. That conclusion was wrong — it was an
artifact of the single-blueprint CE lab, where I had created a SECOND blueprint
(unsupported) whose PUT then 404'd. PCD supports one blueprint per region;
against a demo env with a single real blueprint the write path works, validated
end-to-end through the provider (import -> clean plan -> in-place PUT update of
dns_domain_name -> revert -> state rm; verified via the API).

Design (the write API requires the whole object):
- All attributes are Optional+Computed and the full object is sent on every
  write. After a write, state keeps the user-configured (known) plan values and
  refreshes only unknowns from the server — so the server's re-serialization or
  normalization of a configured attribute (notably the storage_backends_json
  JSON blob) can't trip "inconsistent result after apply". Verified live with
  storage_backends_json set (previously a guaranteed failure).
- storage_backends_json is Sensitive (plaintext driver credentials), required on
  create (PCD 500s a blueprint with no backends), and read back so writes
  preserve the current backends unless changed.
- Delete is a no-op that only removes the resource from Terraform state: a region
  singleton is normally imported, so destroy should stop managing it, not delete
  the cluster-defining blueprint every host/cluster depends on.
- name is ForceNew.

Adversarial review found 6 issues; all fixed: the storage_backends_json /
known-plan round-trip (keep known values), missing UseStateForUnknown on three
bools, warn-not-error on post-write read-back failure, and the no-op delete.
@PF9-pushkar
PF9-pushkar merged commit da4a4b2 into main Jul 14, 2026
5 checks passed
@PF9-pushkar
PF9-pushkar deleted the feat/blueprint-resource branch July 14, 2026 01:43
PF9-pushkar added a commit that referenced this pull request Jul 14, 2026
feat(resmgr): pcd_cluster_blueprint resource (write path) — validated live
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant