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
35 changes: 29 additions & 6 deletions api/v1alpha1/ionoscloudmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ const (
VolumeDiskTypeSSDStandard VolumeDiskType = "SSD Standard"
// VolumeDiskTypeSSDPremium defines the premium SSD disk type.
VolumeDiskTypeSSDPremium VolumeDiskType = "SSD Premium"
// VolumeDiskTypeDAS defines the direct attached storage disk type.
VolumeDiskTypeDAS VolumeDiskType = "DAS"
)

// String returns the string representation of the VolumeDiskType.
Expand All @@ -90,14 +92,18 @@ func (a AvailabilityZone) String() string {
return string(a)
}

// ServerType is the type of server which is created (ENTERPRISE or VCPU).
// ServerType is the type of server which is created (ENTERPRISE, VCPU, CUBE or GPU).
type ServerType string

const (
// ServerTypeEnterprise server of type ENTERPRISE.
ServerTypeEnterprise ServerType = "ENTERPRISE"
// ServerTypeVCPU server of type VCPU.
ServerTypeVCPU ServerType = "VCPU"
// ServerTypeCUBE server of type CUBE.
ServerTypeCUBE ServerType = "CUBE"
// ServerTypeGPU server of type GPU.
ServerTypeGPU ServerType = "GPU"
Comment thread
lucasl0st marked this conversation as resolved.
)

// String returns the string representation of the ServerType.
Expand All @@ -107,6 +113,9 @@ func (a ServerType) String() string {

// IonosCloudMachineSpec defines the desired state of IonosCloudMachine.
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.networkID) || has(self.networkID)", message="networkID is required once set"
// +kubebuilder:validation:XValidation:rule="(self.type != 'CUBE' && self.type != 'GPU') || size(self.templateID) > 0",message="templateID is required when type is CUBE or GPU"
// +kubebuilder:validation:XValidation:rule="(self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID) || size(self.templateID) == 0",message="templateID must only be used with CUBE or GPU type"
// +kubebuilder:validation:XValidation:rule="(self.type != 'VCPU' && self.type != 'CUBE' && self.type != 'GPU') || !has(self.cpuFamily)",message="cpuFamily must not be specified when using VCPU, CUBE or GPU"
type IonosCloudMachineSpec struct {
// ProviderID is the IONOS Cloud provider ID
// will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
Expand All @@ -118,7 +127,17 @@ type IonosCloudMachineSpec struct {
//+kubebuilder:validation:Format=uuid
DatacenterID string `json:"datacenterID"`

// TemplateID is the ID of the template for creating CUBE or GPU servers.
// If a template has GPU cards assigned, then it can only be used to create GPU servers,
// otherwise it can only be used for CUBE servers.
// NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
// Available TemplateIDs can be listed using the cloud api.
//+kubebuilder:validation:Format=uuid
//+optional
TemplateID string `json:"templateID,omitempty"`

// NumCores defines the number of cores for the VM.
// Ignored when TemplateID is specified.
//+kubebuilder:validation:Minimum=1
//+kubebuilder:default=1
//+optional
Expand All @@ -133,6 +152,7 @@ type IonosCloudMachineSpec struct {
// MemoryMB is the memory size for the VM in MB.
// Size must be specified in multiples of 256 MB with a minimum of 1024 MB
// which is required as we are using hot-pluggable RAM by default.
// Ignored when TemplateID is specified.
//+kubebuilder:validation:MultipleOf=1024
//+kubebuilder:validation:Minimum=2048
//+kubebuilder:default=3072
Expand All @@ -144,6 +164,7 @@ type IonosCloudMachineSpec struct {
//
// If not specified, the cloud will select a suitable CPU family
// based on the availability in the data center.
// Ignored when TemplateID is specified.
//+kubebuilder:example=AMD_OPTERON
//+optional
CPUFamily *string `json:"cpuFamily,omitempty"`
Expand Down Expand Up @@ -180,9 +201,10 @@ type IonosCloudMachineSpec struct {
// +kubebuilder:validation:MinLength=1
NetworkID *string `json:"networkID,omitempty"`

// Type is the server type of the VM. Can be either ENTERPRISE or VCPU.
// Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
// Use the types CUBE or GPU together with TemplateID.
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="type is immutable"
//+kubebuilder:validation:Enum=ENTERPRISE;VCPU
//+kubebuilder:validation:Enum=ENTERPRISE;VCPU;CUBE;GPU
//+kubebuilder:default=ENTERPRISE
//+optional
Type ServerType `json:"type,omitempty"`
Expand Down Expand Up @@ -216,12 +238,14 @@ type Volume struct {
Name string `json:"name,omitempty"`

// DiskType defines the type of the hard drive.
//+kubebuilder:validation:Enum=HDD;SSD Standard;SSD Premium
// Ignored for the boot volume when using GPU server type.
//+kubebuilder:validation:Enum=HDD;SSD Standard;SSD Premium;DAS
//+kubebuilder:default=HDD
//+optional
DiskType VolumeDiskType `json:"diskType,omitempty"`

// SizeGB defines the size of the volume in GB
// SizeGB defines the size of the volume in GB.
// Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
//+kubebuilder:validation:Minimum=10
//+kubebuilder:default=20
//+optional
Expand Down Expand Up @@ -392,7 +416,6 @@ type IonosCloudMachine struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

//+kubebuilder:validation:XValidation:rule="self.type != 'VCPU' || !has(self.cpuFamily)",message="cpuFamily must not be specified when using VCPU"
Spec IonosCloudMachineSpec `json:"spec,omitempty"`
Status IonosCloudMachineStatus `json:"status,omitempty"`
}
Expand Down
38 changes: 35 additions & 3 deletions api/v1alpha1/ionoscloudmachine_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
. "github.com/onsi/gomega"
)

const exampleUUID = "ee090ff2-1eef-48ec-a246-a51a33aa4f3a"

func defaultMachine() *IonosCloudMachine {
return &IonosCloudMachine{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -510,22 +512,52 @@ var _ = Describe("IonosCloudMachine Tests", func() {
m.Spec.Type = "this-should-fail"
Expect(k8sClient.Create(context.Background(), m)).ToNot(Succeed())
})
It("should fail if cpuFamily is set and type is VCPU", func() {
DescribeTable("should fail if cpuFamily is set",
func(serverType ServerType) {
m := defaultMachine()
m.Spec.CPUFamily = ptr.To("some-cpu-family")
m.Spec.Type = serverType
if serverType == ServerTypeCUBE || serverType == ServerTypeGPU {
m.Spec.TemplateID = exampleUUID
}
Expect(k8sClient.Create(context.Background(), m)).ToNot(Succeed())
},
Entry("VCPU", ServerTypeVCPU),
Entry("CUBE", ServerTypeCUBE),
Entry("GPU", ServerTypeGPU),
)
It("should fail if templateID is set with ENTERPRISE type", func() {
m := defaultMachine()
m.Spec.CPUFamily = ptr.To("some-cpu-family")
m.Spec.Type = ServerTypeVCPU
m.Spec.Type = ServerTypeEnterprise
m.Spec.TemplateID = exampleUUID
Expect(k8sClient.Create(context.Background(), m)).ToNot(Succeed())
})
DescribeTable("should fail if templateID is missing for",
func(serverType ServerType) {
m := defaultMachine()
m.Spec.Type = serverType
m.Spec.CPUFamily = nil
m.Spec.TemplateID = ""
Expect(k8sClient.Create(context.Background(), m)).ToNot(Succeed())
},
Entry("CUBE", ServerTypeCUBE),
Entry("GPU", ServerTypeGPU),
)
DescribeTable("should work for value",
func(serverType ServerType) {
m := defaultMachine()
m.Spec.Type = serverType
m.Spec.CPUFamily = nil
if serverType == ServerTypeCUBE || serverType == ServerTypeGPU {
m.Spec.TemplateID = exampleUUID
}
Expect(k8sClient.Create(context.Background(), m)).To(Succeed())
Expect(m.Spec.Type).To(Equal(serverType))
},
Entry("ENTERPRISE", ServerTypeEnterprise),
Entry("VCPU", ServerTypeVCPU),
Entry("CUBE", ServerTypeCUBE),
Entry("GPU", ServerTypeGPU),
)
})
Context("Conditions", func() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ spec:

If not specified, the cloud will select a suitable CPU family
based on the availability in the data center.
Ignored when TemplateID is specified.
example: AMD_OPTERON
type: string
datacenterID:
Expand All @@ -189,11 +190,14 @@ spec:
type: string
diskType:
default: HDD
description: DiskType defines the type of the hard drive.
description: |-
DiskType defines the type of the hard drive.
Ignored for the boot volume when using GPU server type.
enum:
- HDD
- SSD Standard
- SSD Premium
- DAS
type: string
image:
description: Image is the image to use for the VM.
Expand Down Expand Up @@ -242,7 +246,9 @@ spec:
type: string
sizeGB:
default: 20
description: SizeGB defines the size of the volume in GB
description: |-
SizeGB defines the size of the volume in GB.
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
minimum: 10
type: integer
required:
Expand Down Expand Up @@ -325,6 +331,7 @@ spec:
MemoryMB is the memory size for the VM in MB.
Size must be specified in multiples of 256 MB with a minimum of 1024 MB
which is required as we are using hot-pluggable RAM by default.
Ignored when TemplateID is specified.
format: int32
minimum: 2048
multipleOf: 1024
Expand All @@ -343,7 +350,9 @@ spec:
rule: self == oldSelf
numCores:
default: 1
description: NumCores defines the number of cores for the VM.
description: |-
NumCores defines the number of cores for the VM.
Ignored when TemplateID is specified.
format: int32
minimum: 1
type: integer
Expand All @@ -352,13 +361,25 @@ spec:
ProviderID is the IONOS Cloud provider ID
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
type: string
templateID:
description: |-
TemplateID is the ID of the template for creating CUBE or GPU servers.
If a template has GPU cards assigned, then it can only be used to create GPU servers,
otherwise it can only be used for CUBE servers.
NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
Available TemplateIDs can be listed using the cloud api.
format: uuid
type: string
type:
default: ENTERPRISE
description: Type is the server type of the VM. Can be either ENTERPRISE
or VCPU.
description: |-
Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
Use the types CUBE or GPU together with TemplateID.
enum:
- ENTERPRISE
- VCPU
- CUBE
- GPU
type: string
x-kubernetes-validations:
- message: type is immutable
Expand All @@ -368,10 +389,17 @@ spec:
- disk
type: object
x-kubernetes-validations:
- message: cpuFamily must not be specified when using VCPU
rule: self.type != 'VCPU' || !has(self.cpuFamily)
- message: networkID is required once set
rule: '!has(oldSelf.networkID) || has(self.networkID)'
- message: templateID is required when type is CUBE or GPU
rule: (self.type != 'CUBE' && self.type != 'GPU') || size(self.templateID)
> 0
- message: templateID must only be used with CUBE or GPU type
rule: (self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID)
|| size(self.templateID) == 0
- message: cpuFamily must not be specified when using VCPU, CUBE or GPU
rule: (self.type != 'VCPU' && self.type != 'CUBE' && self.type != 'GPU')
|| !has(self.cpuFamily)
status:
description: IonosCloudMachineStatus defines the observed state of IonosCloudMachine.
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ spec:

If not specified, the cloud will select a suitable CPU family
based on the availability in the data center.
Ignored when TemplateID is specified.
example: AMD_OPTERON
type: string
datacenterID:
Expand All @@ -209,11 +210,14 @@ spec:
type: string
diskType:
default: HDD
description: DiskType defines the type of the hard drive.
description: |-
DiskType defines the type of the hard drive.
Ignored for the boot volume when using GPU server type.
enum:
- HDD
- SSD Standard
- SSD Premium
- DAS
type: string
image:
description: Image is the image to use for the VM.
Expand Down Expand Up @@ -264,8 +268,9 @@ spec:
type: string
sizeGB:
default: 20
description: SizeGB defines the size of the volume in
GB
description: |-
SizeGB defines the size of the volume in GB.
Ignored when TemplateID of IonosCloudMachineSpec is specified (for the boot volume).
minimum: 10
type: integer
required:
Expand Down Expand Up @@ -349,6 +354,7 @@ spec:
MemoryMB is the memory size for the VM in MB.
Size must be specified in multiples of 256 MB with a minimum of 1024 MB
which is required as we are using hot-pluggable RAM by default.
Ignored when TemplateID is specified.
format: int32
minimum: 2048
multipleOf: 1024
Expand All @@ -367,8 +373,9 @@ spec:
rule: self == oldSelf
numCores:
default: 1
description: NumCores defines the number of cores for the
VM.
description: |-
NumCores defines the number of cores for the VM.
Ignored when TemplateID is specified.
format: int32
minimum: 1
type: integer
Expand All @@ -377,13 +384,25 @@ spec:
ProviderID is the IONOS Cloud provider ID
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
type: string
templateID:
description: |-
TemplateID is the ID of the template for creating CUBE or GPU servers.
If a template has GPU cards assigned, then it can only be used to create GPU servers,
otherwise it can only be used for CUBE servers.
NumCores, MemoryMB, CPUFamily and the size parameter of the first volume (boot Disk) are ignored when this is set.
Available TemplateIDs can be listed using the cloud api.
format: uuid
type: string
type:
default: ENTERPRISE
description: Type is the server type of the VM. Can be either
ENTERPRISE or VCPU.
description: |-
Type is the server type of the VM. Can be either ENTERPRISE, VCPU, CUBE or GPU.
Use the types CUBE or GPU together with TemplateID.
enum:
- ENTERPRISE
- VCPU
- CUBE
- GPU
type: string
x-kubernetes-validations:
- message: type is immutable
Expand All @@ -395,6 +414,16 @@ spec:
x-kubernetes-validations:
- message: networkID is required once set
rule: '!has(oldSelf.networkID) || has(self.networkID)'
- message: templateID is required when type is CUBE or GPU
rule: (self.type != 'CUBE' && self.type != 'GPU') || size(self.templateID)
> 0
- message: templateID must only be used with CUBE or GPU type
rule: (self.type == 'CUBE' || self.type == 'GPU') || !has(self.templateID)
|| size(self.templateID) == 0
- message: cpuFamily must not be specified when using VCPU, CUBE
or GPU
rule: (self.type != 'VCPU' && self.type != 'CUBE' && self.type
!= 'GPU') || !has(self.cpuFamily)
required:
- spec
type: object
Expand Down
Loading
Loading