|
| 1 | +# ADR-007: Resource Type Name Migration |
| 2 | + |
| 3 | +## Status |
| 4 | + |
| 5 | +Accepted |
| 6 | + |
| 7 | +## Date |
| 8 | + |
| 9 | +2026-03-13 |
| 10 | + |
| 11 | +## Context |
| 12 | + |
| 13 | +All resources in this provider use the prefix `proxmox_virtual_environment_` (29 characters), making resource type names verbose and hard to scan. For example, `proxmox_virtual_environment_hagroup`, `proxmox_virtual_environment_network_linux_bridge`. Users and IDE tooling must skip past this boilerplate to reach the meaningful portion of the name. The community has requested shorter prefixes (see [#2133](https://github.com/bpg/terraform-provider-proxmox/issues/2133), [#1231](https://github.com/bpg/terraform-provider-proxmox/issues/1231)). |
| 14 | + |
| 15 | +### Constraints Investigated |
| 16 | + |
| 17 | +Three candidate prefixes were evaluated: `pve_`, `proxmox_`, and `proxmox_virtual_environment_` (status quo). |
| 18 | + |
| 19 | +**Terraform's implied provider resolution** is the binding constraint. Terraform extracts the first word before `_` from a resource type name to determine which provider manages it: |
| 20 | + |
| 21 | +- `proxmox_virtual_environment_hagroup` -> implied provider = `proxmox` (matches `bpg/proxmox`) |
| 22 | +- `proxmox_hagroup` -> implied provider = `proxmox` (matches `bpg/proxmox`) |
| 23 | +- `pve_hagroup` -> implied provider = `pve` (no match — would require a `pve` local name) |
| 24 | + |
| 25 | +For `pve_*` resources to auto-resolve, users would need to declare `pve = { source = "bpg/proxmox" }` in `required_providers`. However, Terraform warns against (and has bugs with) declaring the same source under two local names since v1.2 ([terraform#31196](https://github.com/hashicorp/terraform/issues/31196), [terraform#31218](https://github.com/hashicorp/terraform/pull/31218)). This makes `pve_` impractical without a separate provider binary or registry entry. |
| 26 | + |
| 27 | +**Plugin Framework and Mux** impose no prefix constraints — resource TypeNames can be any non-empty unique string. The prefix convention is advisory only. Both `proxmox_virtual_environment_*` and `proxmox_*` resources can coexist in the same provider binary. |
| 28 | + |
| 29 | +### Summary of Options |
| 30 | + |
| 31 | +| Prefix | Auto-resolves? | Single provider config? | Breaking change? | |
| 32 | +|---------------------------------------------|----------------|-----------------------------|------------------| |
| 33 | +| `proxmox_virtual_environment_` (status quo) | Yes | Yes | No | |
| 34 | +| `proxmox_` | Yes | Yes | Yes (v1.0) | |
| 35 | +| `pve_` | No | No (needs `pve` local name) | Yes + UX cost | |
| 36 | + |
| 37 | +## Decision |
| 38 | + |
| 39 | +Adopt `proxmox_` as the resource type name prefix, migrated in three phases. |
| 40 | + |
| 41 | +### Phase 1: New Resources (immediate, pre-v1.0) |
| 42 | + |
| 43 | +All new Framework resources use the `proxmox_` prefix by hardcoding the TypeName: |
| 44 | + |
| 45 | +```go |
| 46 | +func (r *haRuleResource) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { |
| 47 | + resp.TypeName = "proxmox_harule" |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +The provider's `MetadataResponse.TypeName` remains `"proxmox_virtual_environment"` — it is not changed. Existing resources continue using `req.ProviderTypeName + "_suffix"` unchanged. |
| 52 | + |
| 53 | +**No breaking changes in this phase.** |
| 54 | + |
| 55 | +### Phase 2: Rename Framework Resources (pre-v1.0, transition) |
| 56 | + |
| 57 | +For each existing **Framework** resource, register a second resource struct with the short name alongside the original. The original emits a deprecation warning. |
| 58 | + |
| 59 | +This phase applies only to Framework resources (`fwprovider/`). SDK resources are handled separately in Phase 3. |
| 60 | + |
| 61 | +```go |
| 62 | +// Short-name alias wrapping the original implementation |
| 63 | +type haGroupShort struct{ haGroupResource } |
| 64 | + |
| 65 | +func (r *haGroupShort) Metadata(_ context.Context, _ resource.MetadataRequest, resp *resource.MetadataResponse) { |
| 66 | + resp.TypeName = "proxmox_hagroup" |
| 67 | +} |
| 68 | + |
| 69 | +func (r *haGroupShort) MoveState(ctx context.Context) []resource.StateMover { |
| 70 | + return []resource.StateMover{{ |
| 71 | + StateMover: func(ctx context.Context, req resource.MoveStateRequest, resp *resource.MoveStateResponse) { |
| 72 | + if req.SourceTypeName != "proxmox_virtual_environment_hagroup" { |
| 73 | + return |
| 74 | + } |
| 75 | + // Schema is identical — copy state as-is |
| 76 | + resp.TargetState.Raw = req.SourceRawState |
| 77 | + }, |
| 78 | + }} |
| 79 | +} |
| 80 | +``` |
| 81 | + |
| 82 | +Users migrate at their own pace using Terraform's `moved` block (requires Terraform >= 1.8): |
| 83 | + |
| 84 | +```hcl |
| 85 | +moved { |
| 86 | + from = proxmox_virtual_environment_hagroup.example |
| 87 | + to = proxmox_hagroup.example |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +**No breaking changes in this phase** — both names work simultaneously. |
| 92 | + |
| 93 | +### Phase 3: Migrate SDK Resources to Framework (v1.0) |
| 94 | + |
| 95 | +SDK resources (`proxmoxtf/`) are feature-frozen. As part of v1.0, each SDK resource is rewritten in the Framework provider with the new `proxmox_*` name directly. The old `proxmox_virtual_environment_*` SDK registrations are removed. |
| 96 | + |
| 97 | +Additionally, any remaining long-name Framework resources from Phase 2 that still have dual registrations have their old names removed. |
| 98 | + |
| 99 | +After v1.0, only `proxmox_*` names remain across the entire provider. |
| 100 | + |
| 101 | +**This is a breaking change**, requiring the v1.0 major version bump. |
| 102 | + |
| 103 | +### Scope |
| 104 | + |
| 105 | +This ADR covers **resource type name prefix migration only**. It does not cover SDK-to-Framework schema migration, which is a separate concern with its own state transformation requirements. SDK resources being rewritten in the Framework may have different schemas; those migrations require dedicated `MoveState` implementations that handle attribute mapping, not just prefix renaming. |
| 106 | + |
| 107 | +### Naming Convention Update |
| 108 | + |
| 109 | +This ADR supersedes the resource type name convention in [ADR-003](003-resource-file-organization.md): |
| 110 | + |
| 111 | +| Element | Old Convention | New Convention | |
| 112 | +|---------------------|------------------------------------------------|---------------------------| |
| 113 | +| Resource type names | `proxmox_virtual_environment_{domain}_{name}` | `proxmox_{domain}_{name}` | |
| 114 | + |
| 115 | +New resources **must** use the `proxmox_` prefix. Existing resources retain their current names until Phase 2. |
| 116 | + |
| 117 | +## Consequences |
| 118 | + |
| 119 | +### Positive |
| 120 | + |
| 121 | +- Resource names are 20+ characters shorter (e.g., `proxmox_hagroup` vs `proxmox_virtual_environment_hagroup`) |
| 122 | +- Better IDE autocomplete and Terraform registry browsing |
| 123 | +- Both old and new names auto-resolve to the `proxmox` provider — no user configuration changes needed |
| 124 | +- `moved` block support provides a smooth migration path |
| 125 | +- No separate provider binary or registry entry required |
| 126 | + |
| 127 | +### Negative |
| 128 | + |
| 129 | +- Dual registration in Phase 2 increases the number of registered resources temporarily |
| 130 | +- Phase 3 (v1.0) is a breaking change requiring user migration |
| 131 | +- `MoveState` / cross-type `moved` blocks require Terraform >= 1.8; older versions need manual `terraform state mv` |
| 132 | +- Provider TypeName stays as `proxmox_virtual_environment` which is inconsistent with the new resource prefix — acceptable since it's an internal detail not visible to users |
| 133 | + |
| 134 | +### Migration Risk |
| 135 | + |
| 136 | +For Framework resource renames (Phase 2), the state migration is low-risk: schemas are identical between old and new names, so `MoveState` simply copies the raw state. No attribute transformation is needed. |
| 137 | + |
| 138 | +SDK-to-Framework migrations (Phase 3) carry higher risk due to potential schema differences and are scoped separately from this ADR. |
| 139 | + |
| 140 | +## References |
| 141 | + |
| 142 | +- [#2133: Reduce "proxmox_virtual_environment_" prefix](https://github.com/bpg/terraform-provider-proxmox/issues/2133) |
| 143 | +- [#1231: Related discussion on prefix naming](https://github.com/bpg/terraform-provider-proxmox/issues/1231) |
| 144 | +- [ADR-003: Resource File Organization](003-resource-file-organization.md) — naming conventions (superseded for type names) |
| 145 | +- [Terraform Plugin Framework: State Move](https://developer.hashicorp.com/terraform/plugin/framework/resources/state-move) |
| 146 | +- [Terraform: Moved Block](https://developer.hashicorp.com/terraform/language/modules/develop/refactoring) |
| 147 | +- [Terraform: Provider Requirements](https://developer.hashicorp.com/terraform/language/providers/requirements) — implied provider resolution |
| 148 | +- [terraform#31196](https://github.com/hashicorp/terraform/issues/31196) — duplicate source in required_providers bug |
0 commit comments