terraform-provider-equinix
terraform-provider-equinix copied to clipboard
resource for metal_hardware_reservation
Users wanting to take advantage of hardware reservations may also want to take advantage of dynamic projects. Today, hardware reservations can only be provisioned as server instances within the project the reservation resides. The API provides the ability to move a hardware reservation to a different project.
What would it look like to take advantage of this feature?
resource "metal_hardware_reservation" "hw" {
project_id = var.desired_project_id
}
terraform import metal_hardware_reservation.hw id
terraform apply
This seems like a useful feature but the use of metal_hardware_reservation
would be complicated by the resources not being the sort of resources users would necessarily want to create or delete ephemerally, especially because these are tied to longer-term contracts.
Is a metal_hardware_reservation_project_assignment
resource the only practical way to provide this feature? Are there other metal_hardware_reservation
attributes that the user would want to (or is permitted to) change?
Another example use-case:
A user may want to move a reserved piece of hardware to a project for the scope of a Terraform module, and then on teardown move that reservation back to another project:
data "metal_project" "garage" {
name = "garage" # existing project, not managed by this Terraform config
}
resource "metal_project" "example" {
name = "example"
}
# hypothetical data source arguments, currently id is required
# the changes here would allow for search and return a single resource, best match.
# in the case of multiple matches with provisionable=true,
# we would return any match - effectively implementing 'next-available'
data "metal_hardware_reservation" "foo" {
facility = "ny5"
state = "active" # I assume this means the machine is ready to use, should check.
plan = "c3.small.86"
provisionable = true
# id = ""
# device_id = ""
# spare = "false" -- Can we fip the spare flag?
# If so, Do we need a resource for that or should metal_hardware_reservation_project_assignment
# be metal_hardware_reservation_settings?
}
# hypothetical resource - would move the reservation to a different project on create and on delete
resource "metal_hardware_reservation_project_assignment" "foo" {
# hardware_reservation_id = "reservation-uuid"
hardware_reservation_id = data.metal_hardware_reservation.foo.id
project_id = metal_project.example.project_id
on_delete_project_id = data.metal_project.garage
}
resource "metal_device" "foo" {
hardware_reservation_id = metal_hardware_reservation_project_assignment.foo.hardware_reservation_id
project_id = metal_hardware_reservation_project_assignment.foo.project_id
...
}
Is the on_delete_project_id
required? Can a project be deleted with reservations attached? Do reservations move to another project or become project orphaned?
(note: https://registry.terraform.io/providers/equinix/metal/latest/docs/data-sources/hardware_reservation does not have "metal_
" in the example)
@displague the concept described in your last comment would solve a huge issue for us in programmatically managing reservations over the existing manual process today.
The idea is:
- store reservations in a "garage' project while not in use
- dynamically provision a new project
- grab a list of available reservations
- select a compatible class reservation
- assign the selected reservation to the new project
- provision
Then on destroy
- deprovision the reserved instance
- reassign to "garage" project
- delete the dynamically created project
@t0mk How does this sound to you? I'd like to avoid _attachment
resources, generally, but I'm not sure that we have enough editable attributes for a _settings
resource. (If spare
can be toggled, that would help. Any other editable attributes? Locked (although that is perhaps a device instance property)?)
We could take the good name metal_hardware_reservation
, but I think we may want to use that in the future with self-service reservations: https://metal.equinix.com/developers/docs/deploy/reserved/#requesting-reserved-hardware
@displague @kjw3 Hey! I read through this issue. My first idea is to ask @kjw3 - Are you sure you want to the hw res juggling in Terraform? There is metal-cli, and you could also have someone code it in Golang using Packngo (provided there's support for all the necessary API calls. If not, I can totally help with Packngo functionality).
I read about how to apply for HW reservations and it seems it's quite an async process (requiring review from Equinix). It seems unlikely that a hardware reservation will be created on demand like e.g. a device.
To fix your use-case in Terraform, I would suggest:
- create datasoruce
metal_hardware_reservations
(plural) with filtering like in https://github.com/equinix/terraform-provider-metal/pull/194#issuecomment-937830632 .. that will make it possible to query reservations based on plan and other criteria. - create resource
metal_hardware_reservation_placement
(name up for discussion), which will take 2 args - hw res ID and project ID, and, if the current hw-res-project-ID and the target project ID are different, will make the/move/
API call
metal_hardware_reservation_placement
can record the "from" project on creation into a Computed param from_project_id
(it's present in an existing hw res resource, see below). On Delete, it can then do the reversing /move
call. It will have disabled import because importing the from_project_id
would be messy.
JSON of hw reservatoin resource:
{
"id": "b51df884-a8d5-4bdd-9e2d-415a01805ca3",
"created_at": "2017-08-23T16:38:05Z",
"short_id": "b51df884",
"custom_rate": null,
"project": {
"href": "/metal/v1/projects/52000fb2-ee46-4673-93a8-de2c2bdba33b"
},
"facility": {
"href": "/metal/v1/facilities/2b70eb8f-fa18-47c0-aba7-222a842362fd"
},
"device": null,
"provisionable": true,
"spare": false,
"need_of_service": false,
"plan": {
"id": "9e4ea1ac-296a-4cd7-95c7-72a4e786151d",
"slug": "t1.small.x86",
"name": "t1.small.x86",
"description": "Our Type 0 configuration is a general use \"cloud killer\" server, with a Intel Atom 2.4Ghz processor and 8GB of RAM.",
"line": "reserved",
"specs": {
"cpus": [
{
"count": 1,
"type": "Intel Atom C2550 @ 2.4Ghz"
}
],
"memory": {
"total": "8GB"
},
"drives": [
{
"count": 1,
"size": "80GB",
"type": "SSD"
}
],
"nics": [
{
"count": 2,
"type": "1Gbps"
}
],
"features": {
"raid": false,
"txt": true
}
},
"legacy": true,
"deployment_types": [],
"class": "t1.small.x86",
"pricing": {
"year": 564.48
},
"reservation_pricing": {},
"available_in": [],
"available_in_metros": []
},
"switch_uuid": "c6e273e5"
}
We're not expecting to be able to request reservations on the fly. We are just looking for the ability to automate moving an existing reservation from it's currently assigned project to a another project.
I have thought about scripting this elsewhere utilizing raw API calls. Wanted to see if you all think this makes sense as part of the terraform metal provider.