Skip to content

feat(quotas): compute / network / blockstorage project quota resources - #20

Merged
PF9-pushkar merged 1 commit into
mainfrom
feat/quotas
Jul 12, 2026
Merged

feat(quotas): compute / network / blockstorage project quota resources#20
PF9-pushkar merged 1 commit into
mainfrom
feat/quotas

Conversation

@PF9-pushkar

Copy link
Copy Markdown
Collaborator

Summary

Adds per-project quota management (Phase 3), ported from terraform-provider-openstack v3.4.0:

Resource Service Fields
pcd_compute_quotaset Nova cores, ram, instances, key_pairs, metadata_items, server_groups, … (14)
pcd_networking_quota Neutron network, subnet, port, router, floatingip, security_group[_rule], rbac_policy, subnetpool (9)
pcd_blockstorage_quotaset Cinder volumes, snapshots, gigabytes, per_volume_gigabytes, backups, backup_gigabytes, groups (7)

Design

  • Partial management. Every quota field is Optional+Computed with UseStateForUnknown. Only fields the user sets/changes are PUT (*int + omitempty); the server echoes the rest and they stay stable across plans. Setting a field to 0 sends 0; -1 means unlimited (Neutron).
  • No create API. Create calls Update then reads the values back (same as upstream).
  • Delete is a deliberate no-op — matches upstream schema.RemoveFromState: destroying the resource stops managing the quotas but does not reset them to defaults. gophercloud's reset-to-defaults Delete is intentionally not called.
  • Import: composite <project_id>/<region> id, tolerating the legacy bare <project_id>; project_id and region are ForceNew.

Deliberate deferrals (see DECISIONS.md)

  • Cinder volume_type_quota (per-volume-type quota map via gophercloud Extra) — the most bug-prone part of the port (echo-on-write, read-back-only-for-configured-keys). Deferred so the scalar quotaset ships clean.
  • Nova force and Neutron trunk — exist in gophercloud but not in the upstream schema; omitted to match upstream exactly.

Adversarial review — 2 real bugs found and fixed

A review workflow (3 finder dimensions → adversarial verify each, against Terraform core source) confirmed two defects, both fixed in this branch, both present in all three resources:

  1. readInto error not returned (Create/Update). A transient read-back failure after a successful Update left unknown Computed fields in state; Terraform core's ungated IsWhollyKnown check then raised a spurious "invalid result object after apply". Now Create/Update return on a read-back error.
  2. Explicit region = "" thrashed. Create resolved region with IsNull()||IsUnknown() while Read/Update used == "", so an explicit empty region flipped to config.Region on refresh and (region being ForceNew) forced a perpetual replace. Unified on the IsNull()||IsUnknown() predicate everywhere — the verifier flagged that the naive "fall back on empty" fix would instead cause "inconsistent result after apply".

Testing

  • go build, go vet, gofmt, golangci-lint — clean (0 issues); unit tests pass; terraform fmt clean; docs regenerate cleanly with correct subcategories (Compute / Networking / Block Storage).
  • Per-service acceptance tests (TestAccComputeQuotaset, TestAccNetworkingQuota, TestAccBlockStorageQuotaset): create a project → set quotas → verify via the API → update a field → import. Not run live this session (CE lab credentials unavailable); tracked PENDING in DECISIONS.md.

Add per-project quota management ported from terraform-provider-openstack:

- pcd_compute_quotaset      (Nova, 14 fields)
- pcd_networking_quota      (Neutron, 9 fields)
- pcd_blockstorage_quotaset (Cinder, 7 scalar fields)

Each resource manages a project's quota limits. Design:

- Every quota field is Optional+Computed with UseStateForUnknown, so only the
  fields the user sets/changes are PUT (via *int omitempty); the server echoes
  the rest and they stay stable across plans (partial management).
- No create API: Create calls Update then reads the values back.
- Delete is a deliberate no-op (matches upstream RemoveFromState): destroying
  the resource stops managing the quotas without resetting them to defaults.
- Composite <project_id>/<region> import id, tolerating the legacy bare
  <project_id> form; project_id and region are ForceNew.

Matches upstream field-for-field except: the Cinder per-volume-type quota map
(volume_type_quota) and the gophercloud-only nova "force" / neutron "trunk"
fields are deferred (see DECISIONS.md).

Region resolution uses the same IsNull/IsUnknown predicate in Create, Read, and
Update so an explicit empty region does not thrash; Create and Update return on
a read-back error instead of persisting unknown computed values.

Includes per-service acceptance tests (create project -> set quotas -> verify
via API -> update -> import), examples, and CHANGELOG/DECISIONS entries.
@PF9-pushkar
PF9-pushkar merged commit f4e66ea into main Jul 12, 2026
4 checks passed
@PF9-pushkar
PF9-pushkar deleted the feat/quotas branch July 12, 2026 18:34
PF9-pushkar added a commit that referenced this pull request Jul 14, 2026
feat(quotas): compute / network / blockstorage project quota resources
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