Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,22 @@ type InstanceCreateOptions struct {
DiskEncryption InstanceDiskEncryption `json:"disk_encryption,omitempty"`
PlacementGroup *InstanceCreatePlacementGroupOptions `json:"placement_group,omitempty"`

// LinodeInstanceInterfaces are the Linode Interfaces (including
// RDMA VPC interfaces) to create the new instance with.
// Conflicts with Interfaces and LinodeInterfaces.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
LinodeInstanceInterfaces []LinodeInstanceInterfaceCreateOptions `json:"-"`

// Linode Interfaces to create the new instance with.
// Conflicts with Interfaces.
// Conflicts with Interfaces and LinodeInstanceInterfaces.
//
// Deprecated: Use LinodeInstanceInterfaces instead. LinodeInstanceInterfaces
// additionally allows specifying RDMA VPC interfaces.
// LinodeInterfaces is retained for backwards compatibility.
LinodeInterfaces []LinodeInterfaceCreateOptions `json:"-"`

// Legacy (config) Interfaces to create the new instance with.
// Conflicts with LinodeInterfaces.
// Conflicts with LinodeInterfaces and LinodeInstanceInterfaces.
Interfaces []InstanceConfigInterfaceCreateOptions `json:"-"`

// Creation fields that need to be set explicitly false, "", or 0 use pointers
Expand Down Expand Up @@ -265,6 +275,14 @@ func (i InstanceCreateOptions) MarshalJSON() ([]byte, error) {
return nil, fmt.Errorf("fields Interfaces and LinodeInterfaces cannot be specified together")
}

if i.Interfaces != nil && i.LinodeInstanceInterfaces != nil {
return nil, fmt.Errorf("fields Interfaces and LinodeInstanceInterfaces cannot be specified together")
}
Comment on lines +278 to +280

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment here is because we compare Interfaces and LinodeInstanceInterfaces are set at the same time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yec-akamai, I think that Copilot's comment was referring to lines 259-261 because it is not updated - currently the function compares 3 values (Interfaces, LinodeInterfaces, LinodeInstanceInterfaces), instead of previous 2 (Interfaces, LinodeInterfaces)


if i.LinodeInterfaces != nil && i.LinodeInstanceInterfaces != nil {
return nil, fmt.Errorf("fields LinodeInterfaces and LinodeInstanceInterfaces cannot be specified together")
}

if i.Interfaces != nil {
resultData.Interfaces = i.Interfaces
}
Expand All @@ -273,6 +291,10 @@ func (i InstanceCreateOptions) MarshalJSON() ([]byte, error) {
resultData.Interfaces = i.LinodeInterfaces
}

if i.LinodeInstanceInterfaces != nil {
resultData.Interfaces = i.LinodeInstanceInterfaces
}

return json.Marshal(resultData)
}

Expand Down
76 changes: 76 additions & 0 deletions interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ type LinodeInterface struct {
Public *PublicInterface `json:"public"`
VPC *VPCInterface `json:"vpc"`
VLAN *VLANInterface `json:"vlan"`

// RDMAVPC contains the configuration for an RDMA VPC interface attached
// to a GPUDirect RDMA capable Linode.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
RDMAVPC *RDMAVPCInterface `json:"rdma_vpc"`
}

type InterfaceDefaultRoute struct {
Expand Down Expand Up @@ -111,6 +116,29 @@ type VLANInterface struct {
IPAMAddress *string `json:"ipam_address,omitempty"`
}

// RDMAVPCInterface contains information about an RDMA VPC interface attached
// to a GPUDirect RDMA capable Linode.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterface struct {
VPCID int `json:"vpc_id"`
SubnetID int `json:"subnet_id"`
IPv4 RDMAVPCInterfaceIPv4 `json:"ipv4"`
}

// RDMAVPCInterfaceIPv4 contains the IPv4 configuration for an RDMA VPC interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceIPv4 struct {
Addresses []RDMAVPCInterfaceIPv4Address `json:"addresses"`
}

// RDMAVPCInterfaceIPv4Address represents a single IPv4 address assigned to an
// RDMA VPC interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceIPv4Address struct {
Address string `json:"address"`
Primary bool `json:"primary"`
}

type LinodeInterfaceCreateOptions struct {
FirewallID *int `json:"firewall_id,omitempty"`
DefaultRoute *InterfaceDefaultRoute `json:"default_route,omitempty"`
Expand All @@ -119,10 +147,27 @@ type LinodeInterfaceCreateOptions struct {
VLAN *VLANInterface `json:"vlan,omitempty"`
}

// LinodeInstanceInterfaceCreateOptions specifies a Linode Interface to be
// created as part of a Linode creation request with RDMA VPC options available.
//
// The standalone interface create endpoint does NOT accept RDMA VPC
// interfaces and therefore continues to use LinodeInterfaceCreateOptions.
type LinodeInstanceInterfaceCreateOptions struct {
LinodeInterfaceCreateOptions

// RDMAVPC creates an RDMA VPC interface attached to the new Linode.
// Only one of Public, VPC, VLAN or RDMAVPC may be set per interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
RDMAVPC *RDMAVPCInterfaceCreateOptions `json:"rdma_vpc,omitzero"`
}

type LinodeInterfaceUpdateOptions struct {
DefaultRoute *InterfaceDefaultRoute `json:"default_route,omitempty"`
Public *PublicInterfaceCreateOptions `json:"public,omitempty"`
VPC *VPCInterfaceUpdateOptions `json:"vpc,omitempty"`

// NOTE: RDMA VPC interfaces may not currently be available to all users.
RDMAVPC *RDMAVPCInterfaceUpdateOptions `json:"rdma_vpc,omitzero"`
}

type PublicInterfaceCreateOptions struct {
Expand Down Expand Up @@ -193,6 +238,37 @@ type VPCInterfaceUpdateOptions struct {
IPv6 *VPCInterfaceIPv6CreateOptions `json:"ipv6,omitempty"`
}

// RDMAVPCInterfaceCreateOptions specifies parameters for creating an RDMA VPC
// interface as part of a Linode creation.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceCreateOptions struct {
SubnetID int `json:"subnet_id"`
IPv4 RDMAVPCInterfaceIPv4Options `json:"ipv4,omitzero"`
}

// RDMAVPCInterfaceUpdateOptions specifies the mutable fields of an RDMA VPC
// interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceUpdateOptions struct {
SubnetID int `json:"subnet_id,omitzero"`
IPv4 RDMAVPCInterfaceIPv4Options `json:"ipv4,omitzero"`
}

// RDMAVPCInterfaceIPv4Options specifies IPv4 parameters for an RDMA VPC
// interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceIPv4Options struct {
Addresses []RDMAVPCInterfaceIPv4AddressOptions `json:"addresses,omitzero"`
}

// RDMAVPCInterfaceIPv4AddressOptions represents a single IPv4 address
// configuration for an RDMA VPC interface.
// NOTE: RDMA VPC interfaces may not currently be available to all users.
type RDMAVPCInterfaceIPv4AddressOptions struct {
Address string `json:"address,omitzero"`
Primary *bool `json:"primary,omitzero"`
}
Comment thread
yec-akamai marked this conversation as resolved.

type LinodeInterfacesUpgrade struct {
ConfigID int `json:"config_id"`
DryRun bool `json:"dry_run"`
Expand Down
1 change: 1 addition & 0 deletions regions.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
CapabilityDistributedPlans string = "Distributed Plans"
CapabilityEdgePlans string = "Edge Plans"
CapabilityGPU string = "GPU Linodes"
CapabilityGPUDirectRDMA string = "GPUDirect RDMA"
CapabilityKubernetesEnterprise string = "Kubernetes Enterprise"
CapabilityKubernetesEnterpriseBYOVPC string = "Kubernetes Enterprise BYO VPC"
CapabilityKubernetesEnterpriseDualStack string = "Kubernetes Enterprise Dual Stack"
Expand Down
27 changes: 27 additions & 0 deletions test/unit/fixtures/interface_get_rdma_vpc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"id": 10,
"mac_address": "22:00:f2:9e:d3:48",
"created": "2026-03-12T09:54:34",
"updated": "2026-03-12T09:54:35",
"default_route": {
"ipv4": false,
"ipv6": false
},
"version": 1,
"public": null,
"vpc": null,
"vlan": null,
"rdma_vpc": {
"vpc_id": 7,
"subnet_id": 8,
"ipv4": {
"addresses": [
{
"address": "10.0.0.2",
"primary": true
}
]
}
}
}

92 changes: 92 additions & 0 deletions test/unit/fixtures/interface_list_with_rdma.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{
"data": [
{
"id": 10,
"mac_address": "22:00:f2:9e:d3:48",
"created": "2026-03-12T09:54:34",
"updated": "2026-03-12T09:54:35",
"default_route": {
"ipv4": false,
"ipv6": false
},
"version": 1,
"public": null,
"vpc": null,
"vlan": null,
"rdma_vpc": {
"vpc_id": 39,
"subnet_id": 1234,
"ipv4": {
"addresses": [
{
"address": "10.0.0.1",
"primary": true
}
]
}
}
},
{
"id": 11,
"mac_address": "22:00:f2:9e:d3:49",
"created": "2026-03-12T09:54:34",
"updated": "2026-03-12T09:54:35",
"default_route": {
"ipv4": false,
"ipv6": false
},
"version": 1,
"public": null,
"vpc": null,
"vlan": null,
"rdma_vpc": {
"vpc_id": 39,
"subnet_id": 1234,
"ipv4": {
"addresses": [
{
"address": "10.0.0.25",
"primary": true
}
]
}
}
},
{
"id": 12,
"mac_address": "22:00:f2:9e:d3:4a",
"created": "2026-03-12T09:54:34",
"updated": "2026-03-12T09:54:35",
"default_route": {
"ipv4": true,
"ipv6": false
},
"version": 1,
"public": null,
"vlan": null,
"rdma_vpc": null,
"vpc": {
"vpc_id": 3,
"subnet_id": 4,
"ipv4": {
"addresses": [
{
"address": "10.0.0.25",
"primary": true
}
],
"ranges": []
},
"ipv6": {
"slaac": [],
"ranges": [],
"is_public": null
}
}
}
],
"page": 1,
"pages": 1,
"results": 3
}

27 changes: 27 additions & 0 deletions test/unit/fixtures/interface_update_rdma_vpc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"id": 10,
"mac_address": "22:00:f2:9e:d3:48",
"created": "2026-03-12T09:54:34",
"updated": "2026-03-13T10:00:00",
"default_route": {
"ipv4": false,
"ipv6": false
},
"version": 2,
"public": null,
"vpc": null,
"vlan": null,
"rdma_vpc": {
"vpc_id": 7,
"subnet_id": 9,
"ipv4": {
"addresses": [
{
"address": "10.0.1.5",
"primary": true
}
]
}
}
}

25 changes: 25 additions & 0 deletions test/unit/fixtures/vpc_rdma_create.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"id": 39,
"label": "new-rdma-vpc",
"vpc_type": "rdma",
"description": "A new RDMA VPC",
"region": "fake-cph-5",
"ipv6": [],
"subnets": [
{
"id": 40,
"label": "rdma-subnet-1",
"ipv4": "10.0.0.0/24",
"vpc_type": "rdma",
"ipv6": [],
"linodes": [],
"databases": [],
"nodebalancers": [],
"created": "2026-03-12T09:30:01",
"updated": "2026-03-12T09:30:01"
}
],
"created": "2026-03-12T09:30:01",
"updated": "2026-03-12T09:30:01"
}

36 changes: 36 additions & 0 deletions test/unit/fixtures/vpc_rdma_get.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"created": "2026-03-12T09:30:01",
"description": "RDMA VPC for GPUDirect",
"id": 7,
"label": "test-vpc-rdma",
"vpc_type": "rdma",
"region": "fake-cph-5",
"ipv6": [],
"subnets": [
{
"id": 8,
"label": "rdma-subnet",
"ipv4": "10.0.0.0/8",
"vpc_type": "rdma",
"ipv6": [],
"linodes": [
{
"id": 506958,
"interfaces": [
{
"id": 10,
"config_id": null,
"active": false
}
]
}
],
"databases": [],
"nodebalancers": [],
"created": "2026-03-12T09:51:58",
"updated": "2026-03-12T09:51:58"
}
],
"updated": "2026-03-12T09:30:01"
}

Loading
Loading