fix(resmgr): terraform destroy deletes the cluster blueprint (PCD-9783) - #49
Merged
Conversation
pcd_cluster_blueprint's Delete was a deliberate no-op: destroy removed the resource from state and never called resmgr, on the reasoning that a region's single blueprint is normally imported and should merely stop being managed. That is not how a Terraform resource is expected to behave. `terraform destroy` reported the blueprint destroyed while it lived on in the region, and nothing short of the PCD UI could remove it. Delete now issues DELETE /resmgr/v2/blueprint/<name>. A blueprint that is already gone (404) is the outcome destroy wants, so it is success; any other refusal fails the destroy instead of being hidden, since a destroy that reports success over a blueprint that still exists was the bug. Users who only want to stop managing an imported blueprint have `terraform state rm`, which the schema description and docs now say. Verified on the CE lab (2026.4) by importing the region's blueprint, cluster, host config and hyp1's three cluster roles into a scratch state and running one `terraform destroy`: all six were removed in dependency order and GET /resmgr/v2/blueprint listed nothing afterwards. Terraform's graph puts the host config (which references the blueprint by name) before the blueprint, so resmgr never saw the delete while a dependent still stood.
Dependabot alert 4 on main: gRPC-Go heap memory exhaustion via HTTP/2 DATA frame fragmentation, fixed in 1.83.1. The provider's gRPC server only serves the local Terraform CLI over a private channel, so exposure was minimal; bumped all the same. go mod tidy also moved genproto/googleapis/rpc to the matching snapshot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes PCD-9783:
terraform destroyof apcd_cluster_blueprintreported success but left the blueprint in PCD.Root cause
Deletewas a deliberate no-op (introduced with the resource in fffa1d5): destroy dropped the resource from state and never called resmgr, on the reasoning that a region's single blueprint is normally imported and should only stop being managed. That contradicts how Terraform resources are expected to behave, and nothing short of the PCD UI could remove the blueprint.Change
Deletenow issuesDELETE /resmgr/v2/blueprint/<name>. A 404 (already gone) is success; any other refusal fails the destroy instead of being hidden.pcd_host_configviacluster_name, clusters, host roles) must go first, and thatterraform state rmis the way to stop managing an imported blueprint without deleting it.google.golang.org/grpcto 1.83.1 for Dependabot alert 4 (GHSA-vp52-pcj8-j9qc), with a Security changelog entry; same minimal-exposure reasoning as the 0.1.9 gRPC bump.Verification
Static:
go build,go vet,gofmt,golangci-lint(0 issues),go test ./internal/...all green.Live, on the CE lab (PCD 2026.4), using a dev build of this branch: the region's existing blueprint
ce-lab-bp, clusterce-lab, host confighyp-2nicand hyp1'shypervisor,image-libraryandpersistent-storageroles were imported into a scratch state (workloads cleared first via the API, since PCD refuses the storage deauth while volumes exist), then destroyed with a singleterraform destroy:Afterwards
GET /resmgr/v2/blueprint,/clustersand/hostconfigsall returned empty lists. Terraform's graph ordered the host config (which references the blueprint by name) before the blueprint, so resmgr never saw the blueprint delete while a dependent still stood. hyp1's roles were still converging off at that moment (resmgr's asynchronous deauth); once it landed, the testsuite'sregion_emptyjudge reportedok=True detail=emptywith both hosts atroles=[].Fresh-lab zero-to-hero (854b7e7). The lab was then rebuilt from scratch (delete-ce-lab / create-ce-lab, one hypervisor, no config) and the pcd-tf-testsuite z2h case was run in its apply-then-destroy mode against a dev build of this branch: blueprint, Synology-backed storage and volume type, flat network/subnet/security group, hypervisor + image-library + persistent-storage roles on hyp1, a cirros image and a VM with an attached volume. Every judge passed (blueprint/hostconfig/cluster JSON match, roles ok, cinder-volume up, image volume-backed, server ACTIVE, volume in-use, plan clean, ping). One
terraform destroythen removed all of it, ending with the suite'sregion_emptyjudge green. It took the suite's usual three attempts while resmgr's asynchronous deauth refused the host-config unassign (403 HostInAuthState); the blueprint delete happened through the provider on the final pass. 17 min end to end.Note for pcd-tf-testsuite
Its teardown calls
api.delete_blueprint("ts-bp")with the comment "provider Delete is state-only by design". That call already tolerates 404, so it keeps working, but the comment is now stale.