diff --git a/lke_node_pools.go b/lke_node_pools.go index 335863b67..4c7773f06 100644 --- a/lke_node_pools.go +++ b/lke_node_pools.go @@ -71,6 +71,28 @@ type LKENodePoolIsolationCreateOptions struct { PublicIPv6 *bool `json:"public_ipv6,omitzero"` } +// LKENodePoolInterfaceType represents the type of a node pool network interface. +type LKENodePoolInterfaceType string + +const ( + // LKENodePoolInterfaceTypeVPC is a standard VPC interface (must be first and represents the cluster VPC). + LKENodePoolInterfaceTypeVPC LKENodePoolInterfaceType = "vpc" + // LKENodePoolInterfaceTypeRDMAVPC is an RDMA-capable VPC interface (LKE Enterprise only). + LKENodePoolInterfaceTypeRDMAVPC LKENodePoolInterfaceType = "rdma_vpc" +) + +// LKENodePoolInterface describes one VPC-backed interface attached to nodes in the pool. +type LKENodePoolInterface struct { + Type LKENodePoolInterfaceType `json:"type"` + VPCID int `json:"vpc_id"` + SubnetID int `json:"subnet_id"` +} + +// LKENodePoolNetworking holds the ordered list of VPC-backed interfaces for an LKE Enterprise node pool. +type LKENodePoolNetworking struct { + Interfaces []LKENodePoolInterface `json:"interfaces"` +} + // LKENodePoolLabels represents Kubernetes labels to add to an LKENodePool type LKENodePoolLabels map[string]string @@ -94,6 +116,10 @@ type LKENodePool struct { // Isolation may not currently be available to all users. Isolation *LKENodePoolIsolation `json:"isolation"` + // Networking holds the effective VPC-backed interface configuration for LKE Enterprise node pools. + // It is read-only after creation. + Networking *LKENodePoolNetworking `json:"networking,omitzero"` + // K8sVersion and UpdateStrategy are only for LKE Enterprise to support node pool upgrades. // It may not currently be available to all users and is under v4beta. K8sVersion *string `json:"k8s_version,omitzero"` @@ -119,6 +145,11 @@ type LKENodePoolCreateOptions struct { // Isolation may not currently be available to all users. Isolation *LKENodePoolIsolationCreateOptions `json:"isolation,omitzero"` + // Networking configures the ordered set of VPC-backed interfaces for LKE Enterprise node pools. + // Accepted only at creation time; immutable after the pool is created. + // NOTE: Networking may not currently be available to all users and can only be used with v4beta. + Networking *LKENodePoolNetworking `json:"networking,omitzero"` + // K8sVersion and UpdateStrategy only works for LKE Enterprise to support node pool upgrades. // It may not currently be available to all users and is under v4beta. K8sVersion *string `json:"k8s_version,omitzero"` @@ -166,6 +197,8 @@ func (l LKENodePool) GetCreateOptions() (o LKENodePoolCreateOptions) { } } + o.Networking = l.Networking + return o } diff --git a/test/unit/fixtures/lke_node_pool_rdma_create.json b/test/unit/fixtures/lke_node_pool_rdma_create.json new file mode 100644 index 000000000..852e399f5 --- /dev/null +++ b/test/unit/fixtures/lke_node_pool_rdma_create.json @@ -0,0 +1,38 @@ +{ + "id": 99001, + "count": 6, + "type": "g3-gpu-rtxpro6000-blackwell-rdma-2", + "label": "rdma-pool", + "disks": [], + "tags": [], + "labels": {}, + "taints": [], + "autoscaler": { + "enabled": true, + "min": 3, + "max": 12 + }, + "disk_encryption": "enabled", + "k8s_version": "v1.31.8+lke3", + "update_strategy": "rolling_update", + "firewall_id": 12345, + "networking": { + "interfaces": [ + { + "type": "vpc", + "vpc_id": 10001, + "subnet_id": 20001 + }, + { + "type": "rdma_vpc", + "vpc_id": 12345, + "subnet_id": 45678 + }, + { + "type": "rdma_vpc", + "vpc_id": 12345, + "subnet_id": 91012 + } + ] + } +} diff --git a/test/unit/fixtures/lke_node_pool_rdma_get.json b/test/unit/fixtures/lke_node_pool_rdma_get.json new file mode 100644 index 000000000..852e399f5 --- /dev/null +++ b/test/unit/fixtures/lke_node_pool_rdma_get.json @@ -0,0 +1,38 @@ +{ + "id": 99001, + "count": 6, + "type": "g3-gpu-rtxpro6000-blackwell-rdma-2", + "label": "rdma-pool", + "disks": [], + "tags": [], + "labels": {}, + "taints": [], + "autoscaler": { + "enabled": true, + "min": 3, + "max": 12 + }, + "disk_encryption": "enabled", + "k8s_version": "v1.31.8+lke3", + "update_strategy": "rolling_update", + "firewall_id": 12345, + "networking": { + "interfaces": [ + { + "type": "vpc", + "vpc_id": 10001, + "subnet_id": 20001 + }, + { + "type": "rdma_vpc", + "vpc_id": 12345, + "subnet_id": 45678 + }, + { + "type": "rdma_vpc", + "vpc_id": 12345, + "subnet_id": 91012 + } + ] + } +} diff --git a/test/unit/lke_node_pools_test.go b/test/unit/lke_node_pools_test.go index 2dd26dac1..a56ba13f9 100644 --- a/test/unit/lke_node_pools_test.go +++ b/test/unit/lke_node_pools_test.go @@ -231,6 +231,73 @@ func TestLKEEnterpriseNodePool_Create(t *testing.T) { assert.Equal(t, 12345, *nodePool.FirewallID) } +func TestLKENodePoolRDMA_Create(t *testing.T) { + fixtureData, err := fixtures.GetFixture("lke_node_pool_rdma_create") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + createOptions := linodego.LKENodePoolCreateOptions{ + Count: 6, + Type: "g3-gpu-rtxpro6000-blackwell-rdma-2", + K8sVersion: linodego.Pointer("v1.31.8+lke3"), + UpdateStrategy: linodego.Pointer(linodego.LKENodePoolRollingUpdate), + Label: linodego.Pointer("rdma-pool"), + FirewallID: linodego.Pointer(12345), + Networking: &linodego.LKENodePoolNetworking{ + Interfaces: []linodego.LKENodePoolInterface{ + {Type: linodego.LKENodePoolInterfaceTypeVPC, VPCID: 10001, SubnetID: 20001}, + {Type: linodego.LKENodePoolInterfaceTypeRDMAVPC, VPCID: 12345, SubnetID: 45678}, + {Type: linodego.LKENodePoolInterfaceTypeRDMAVPC, VPCID: 12345, SubnetID: 91012}, + }, + }, + } + + base.MockPost("lke/clusters/123/pools", fixtureData) + + nodePool, err := base.Client.CreateLKENodePool(context.Background(), 123, createOptions) + assert.NoError(t, err) + assert.Equal(t, "g3-gpu-rtxpro6000-blackwell-rdma-2", nodePool.Type) + assert.Equal(t, 6, nodePool.Count) + if assert.NotNil(t, nodePool.Networking) { + ifaces := nodePool.Networking.Interfaces + assert.Len(t, ifaces, 3) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeVPC, ifaces[0].Type) + assert.Equal(t, 10001, ifaces[0].VPCID) + assert.Equal(t, 20001, ifaces[0].SubnetID) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeRDMAVPC, ifaces[1].Type) + assert.Equal(t, 12345, ifaces[1].VPCID) + assert.Equal(t, 45678, ifaces[1].SubnetID) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeRDMAVPC, ifaces[2].Type) + assert.Equal(t, 91012, ifaces[2].SubnetID) + } +} + +func TestLKENodePoolRDMA_Get(t *testing.T) { + fixtureData, err := fixtures.GetFixture("lke_node_pool_rdma_get") + assert.NoError(t, err) + + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("lke/clusters/123/pools/99001", fixtureData) + + nodePool, err := base.Client.GetLKENodePool(context.Background(), 123, 99001) + assert.NoError(t, err) + assert.Equal(t, 99001, nodePool.ID) + assert.Equal(t, "g3-gpu-rtxpro6000-blackwell-rdma-2", nodePool.Type) + if assert.NotNil(t, nodePool.Networking) { + ifaces := nodePool.Networking.Interfaces + assert.Len(t, ifaces, 3) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeVPC, ifaces[0].Type) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeRDMAVPC, ifaces[1].Type) + assert.Equal(t, linodego.LKENodePoolInterfaceTypeRDMAVPC, ifaces[2].Type) + } +} + func TestLKEEnterpriseNodePool_Update(t *testing.T) { fixtureData, err := fixtures.GetFixture("lke_e_node_pool_update") assert.NoError(t, err)