Files
terraform-provider-binarylane/openapi.json
T
Oscar Hermoso 725fa71248 💽 Add disks attribute to server resource & data source
Adds `disks` to `binarylane_server` and its data source, so a server's storage
can be split across several disks. Leave it unset and Binary Lane keeps managing
a single disk sized by `disk`; set it and it must describe every disk, including
the primary.

- The schema is generated the same way as `advanced_features`:
  scripts/data/server_disks.json is spliced into provider_code_spec.json by
  extend-provider.sh, with the list validator in
  internal/resources/server_disks_validators.go.
- `disk` remains the server's total storage. sum(disks[*].size_gigabytes) cannot
  exceed it, and any remainder is left unallocated.
- Create carves the additional disks out of the primary, which Binary Lane sizes
  to the whole total. Update frees space before the server's resize action and
  claims it afterwards, persisting what was actually done if a step fails.
- Disks are matched across plans by description, or by being the primary, and are
  numbered within a description so a server can have two disks sharing one.
- `disks` is returned in the order the configuration lists them, since Terraform
  requires a list's elements to stay where they were planned.
- Shrinking a disk warns at plan time, as does attaching additional disks
  alongside `user_data` that cloud-init may still be running.

Also bumps the OpenAPI schema to v0.39.2, and fixes two pre-existing bugs found
running the acceptance suite against real infrastructure: `advanced_features`
and `public_ipv6_addresses` weren't carried forward from state on a no-op
replan, so they planned as unknown on every apply.

🧪 Assert disks inline, and cover ordering in the acceptance tests

Drops the checkServerDisks/expectedDisk helper for the inline
TestCheckResourceAttr and TestCheckResourceAttrSet calls every other check in
this file uses.

Replaces the TestServerDisksToList unit test with the equivalent assertions in
TestServerResourceCreateWithDisks, which already reorders the disks of a real
server: the resource keeps the order its configuration lists them in, while the
data source, which has no order of its own, lists the primary disk first and the
rest by id. Both disks sharing the description "data" cover the duplicate case.

🧪 Pin disk ids across a list shift

Removing a disk shifts every disk after it down a position, which is where
terraform-plugin-framework#720 bites: Terraform merges prior state into the
proposed plan positionally, so the disk that moved up would inherit the id of
the one that was deleted, and the provider would resize the wrong disk.

planServerDisks matches by description (and by being the primary) instead of by
index, so this only asserts what should already hold: "alpha" and "beta" keep
the disks they had when "zeta" is removed from in front of them.

🏗️ Plan `disks` from a plan modifier on the attribute

Moves the planning of a configured `disks` out of the resource's ModifyPlan and
onto the attribute itself, as disksPlanModifier in internal/resources — the same
place, and declared the same way in scripts/data/server_disks.json, as
disksValidator.

Behaviour is unchanged: Terraform builds a list's proposed plan by merging prior
state in element by element, so removing a disk hands the disks after it the id
of their predecessor. The modifier plans the list from the configuration
instead, taking each disk's server-assigned values from the disk it matches in
prior state. DiskKey/DiskKeyer and DiskShrinkWarning move with it and are now
exported, since ordering and reconciliation match disks by the same rule.

What stays in ModifyPlan is the case `disks` is not configured, where what
happens to the disks depends on `disk` — the server's total, which ModifyPlan
resolves from state a few lines earlier, after attribute plan modifiers have
already run.

🏗️ Plan an unset `disks` on create from the plan modifier too

The creation case needs nothing but the absence of prior state, so it moves next
to the rest of the disk planning.

The remaining case — `disks` left out of the configuration on an existing server
— stays in ModifyPlan, and can't move: it depends on `disk`, the server's total,
which ModifyPlan resolves from state only after attribute plan modifiers have
run. Reading `disk` from the plan inside the modifier plans the disks as unknown
on every no-op replan, which TestServerResourceRename catches:

    ~ disks = [ - { id = 1 ... } ] -> (known after apply)
    Plan: 0 to add, 1 to change, 0 to destroy.

Working the total out from the configuration inside the modifier would restate a
rule that already lives in ModifyPlan, so it stays where the value it needs is.

🧪 Try `disks` as a SetNestedAttribute

A set has no order, so everything that existed to keep a list's elements where
Terraform planned them goes away: serverDisksToList's ranking and its `order`
argument threaded through five call sites become a three-line
types.SetValueFrom, and a configuration can list its disks however it likes.

Verified against the live API: create with duplicate descriptions, update
(resize, add, remove), dropping `disks`, reordering, and resizing one of two
disks that share a description — the case a set is least equipped for, since it
has no positions to match duplicates by.

Costs: a resize renders as a remove/add pair rather than an in-place change (the
id is preserved in both halves), and tests need checkDiskId to find a disk,
since a set has no index to address one with.

🪞 Reconcile disks as binarylane.Disk, not as Terraform values

binarylane.Disk carries tfsdk tags for exactly the attributes `disks` has, so a
configured set reflects straight into it. splitDisks now hands Create and Update
the API's own type, which is what the disks they compare against already are:
the comparison that read `disk.SizeGigabytes.ValueInt64() <
int64(other.SizeGigabytes)` now reads `disk.SizeGigabytes <
other.SizeGigabytes`. Eight value-unwrapping conversions go with it.

The plan modifier keeps building Terraform values by hand, since the attributes
Binary Lane assigns are still unknown while it runs.

🧪 Restore `disks` to ListNestedAttribute

Co-Authored-By: Marais Rossouw <maraisr@users.noreply.github.com>
2026-08-30 18:12:02 +08:00

423 KiB