Implement Connections resources
displague opened this issue · 7 comments
What problem are you facing?
Equinix Metal offers Connections through Equinix Fabric. These are not made available through this provider.
How could the Equinix Metal Terraform Provider help solve your problem?
Implement Datasources
- #41 Connections (by organization or project)
- #41 Connection Ports
- #41 Virtual Circuits Datasource
- Events (We haven't implemented these for other resources. I'm not sure what benefit they provide in Terraform. Listed only for completeness.)
- Connections (Not planned)
- Ports (Not planned)
- Virtual Circuits (Not planned)
Implement Resources
- Connections Resource #76
- Connection Ports (computed)
-
Virtual Circuits (computed)(Use independent virtual-circuit datasource or resources)
- Virtual Circuits Resource #92
Depends on packethost/packngo#228 packethost/packngo#234 (more context there)
Initial Connection shape proposal (see comments for revisions):
resource "metal_connection" "conn" {
// create only
type = "string" // shared | dedicated
speed = 0 // int bps, rather than permitted "123 mbps" format
organization = "string" // GET returns this as {href}
metro = "string" // returned as {href}
facility = "string" // returned as {href}, create either metro or facility, both will be returned
// create and update
name = "string"
description = "string"
contact_email = "string"
redundancy = "string" // primary | redundant
tags = [
"string"
]
// read only
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
status = "string"
ports {
primary {
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
role = "string"
status = "string"
switch_id = "string"
// virtual_circuits is promoted to connection level property
}
secondary {
// same as primary, except "role=secondary"
}
}
// set type (multiple, removable, updateable)
// these are read from "ports" above, included in /connection/{id}/ports/{id}
// (virtual_circuits list can come from either port, they should have the same list,
// we can map by id when sync'ing, just-in-case)
// these are updated or deleted through /virtual-circuits/{id}
virtual_circuit {
// create only
nni_vlan = 0
project = "" // returned as {href}
// create and update
name = "string"
description = "string"
speed = 0
tags = [
"string"
]
vnid = 0
// read only
status = "string"
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
virtual_network = "" // returned as {href}
// hide this if it is redundant to nni_vlan or vnid?
}
}
@t0mk I updated the checkboxes here and added a sketch of the metal_connection resource (which goes along with the thinking for metal_device changes, bringing ports to the surface)
The fields that I included (and grouped into create/update/readonly) are based on the current API spec documentation (hopefully accurate).
I think users may prefer to terraform import
the connection, until terraform apply
can create connections in a reasonable amount of time. Users can then modify the connection and virtual-circuits in Terraform.
I made some assumptions above, and they are not all accurate:
- the only returned connection ports will be ‘primary’ and ‘secondary’ (this helps to make them usable in terraform)
- virtual circuits returned for each port are identical and can be treated as a direct property of the connection, their relationship to ports is a side-effect.
- users can not interact with the ports, only read their values.
- virtual circuits only make sense in the same project as their connection
connections are always part of a single projectconnections are organization resources
This broadens the scope of connections and the ramifications of deleting a connection. This also increases the requirements for importing a connection. Users will need to import and manage all virtual-circuits across the connection in this one Terraform resource. Deleting the connection will delete all of the virtual-circuits.
The ramifications of deleting an organization resource are also large in scope. In order to the follow the API, I'm updating the proposed shape to include project id in each virtual-circuit, not within the connection.
I'm reconsidering virtual_circuit
as a property of the metal_connection
.
Independent metal_virtual_circuit
resource would be usable with datasource'd connections and would avoid the large upfront requirement of pre-populating an imported connection. Even if future versions of Terraform can generate config during import, independent virtual_circuit resources, which are project scoped, are lighter and less risky to manage without configuring them as a property of the connection.
resource "metal_connection" "conn" {
// create only
type = "string" // shared | dedicated
speed = 0 // int bps, rather than permitted "123 mbps" format
organization = "string" // GET returns this as {href}
metro = "string" // returned as {href}
facility = "string" // returned as {href}, create either metro or facility, both will be returned
// create and update
name = "string"
description = "string"
contact_email = "string"
redundancy = "string" // primary | redundant
tags = [
"string"
]
// read only
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
status = "string"
ports {
primary {
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
role = "string"
status = "string"
switch_id = "string"
// virtual_circuits is promoted to a new resource type for updates,
// they are a computed field, type Map (indexed by circuit id) here
virtual_circuits = {
{id} = {
// read-only
nni_vlan = 0
project = "" // returned as {href}
name = "string"
description = "string"
speed = 0
tags = [
"string"
]
vnid = 0
status = "string"
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
virtual_network = "" // returned as {href}
// hide this if it is redundant to nni_vlan or vnid?
}
}
}
secondary {
// same as primary, except "role=secondary"
}
}
}
// these are read, updated and deleted through /virtual-circuits/{id}
// they are created through /connection/{id}/ports/{id}
resource "metal_virtual_circuit" "circuit_short" {
// required path parameters, dependent resources
// connection_id = "" // this appears to be a value we can lookup by port id,
port_id = metal_connection.conn.ports.primary.id // connected_port is a /port/{id} property
// create only
nni_vlan = 0
project = "" // returned as {href}
// create and update
name = "string"
description = "string"
speed = 0
tags = [
"string"
]
vnid = 0
// read only
status = "string"
id = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
virtual_network = "" // returned as {href}
// hide this if it is redundant to nni_vlan or vnid?
// connection_id can be computed if we do not require it for creation
}
I'm making an assumption that connection ports can only include a single role=primary and role=secondary port, this may not be accurate.
Another reason for separating the virtual-circuits from the connections is that these resources, while dependent have different scope. Virtual-circuits are project scoped, while connections are organization scoped. Project scoped API keys may be able to manage virtual-circuits, but not connections.
I imagine that depending how we implement the lookup fields, we may run into problems with project API keys not having access to /organization/{id}/connections, /ports/ or other resources.
Making project api keys usable with these resources is not a goal, but it is something to consider while designing this.
That looks good to me. The only thing i would add is having the ability to edit the Virtual Circuit resource, main value to edit would be the vnid
associated to the virtual circuit.
In the comment above, you would be able to edit vnid:
resource "metal_virtual_circuit" "circuit_short" {
vnid = 0
...
}
The metal_connection
resource would have a read-only computed value too:
metal_connection.conn.ports.primary.virtual_circuits.{id}.vnid
metal_connection.conn.ports.secondary.virtual_circuits.{id}.vnid
(The initial draft allowed for updating vnid
within the metal_connection
, but I found reasons not to like that approach.