Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Ability to use VCPUs #136

Merged
merged 3 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
23 changes: 23 additions & 0 deletions api/v1alpha1/ionoscloudmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ func (a AvailabilityZone) String() string {
return string(a)
}

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

const (
// ServerTypeEnterprise server of type ENTERPRISE.
ServerTypeEnterprise ServerType = "ENTERPRISE"
// ServerTypeVCpu server of type VCPU.
ServerTypeVCpu ServerType = "VCPU"
jriedel-ionos marked this conversation as resolved.
Show resolved Hide resolved
)

// String returns the string representation of the ServerType.
func (a ServerType) String() string {
return string(a)
}

// IonosCloudMachineSpec defines the desired state of IonosCloudMachine.
type IonosCloudMachineSpec struct {
// ProviderID is the IONOS Cloud provider ID
Expand Down Expand Up @@ -149,6 +164,13 @@ type IonosCloudMachineSpec struct {
//+kubebuilder:validation:XValidation:rule=`self == "AUTO" || self.matches("((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$")`,message="failoverIP must be either 'AUTO' or a valid IPv4 address"
//+optional
FailoverIP *string `json:"failoverIP,omitempty"`

// Type is the server type of the VM. Can be either ENTERPRISE or VCPU.
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="type is immutable"
//+kubebuilder:validation:Enum=ENTERPRISE;VCPU
//+kubebuilder:default=ENTERPRISE
//+optional
Type ServerType `json:"type,omitempty"`
}

// Networks contains a list of additional LAN IDs
Expand Down Expand Up @@ -293,6 +315,7 @@ 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
33 changes: 32 additions & 1 deletion api/v1alpha1/ionoscloudmachine_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ var _ = Describe("IonosCloudMachine Tests", func() {
Expect(m.Spec.Disk.SizeGB).To(Equal(want))
})
})
Context("Type", func() {
Context("DiskType", func() {
It("should default to HDD", func() {
m := defaultMachine()
// because DiskType is a string, setting the value as "" is the same as not setting anything
Expand Down Expand Up @@ -384,6 +384,37 @@ var _ = Describe("IonosCloudMachine Tests", func() {
Expect(k8sClient.Update(context.Background(), m)).ToNot(Succeed())
})
})
Context("ServerType", func() {
It("should default to ENTERPRISE", func() {
m := defaultMachine()
// because Type is a string, setting the value as "" is the same as not setting anything
m.Spec.Type = ""
Expect(k8sClient.Create(context.Background(), m)).To(Succeed())
Expect(m.Spec.Type).To(Equal(ServerTypeEnterprise))
})
It("should fail if not part of the enum", func() {
m := defaultMachine()
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() {
m := defaultMachine()
m.Spec.CPUFamily = ptr.To("some-cpu-family")
m.Spec.Type = ServerTypeVCpu
Expect(k8sClient.Create(context.Background(), m)).ToNot(Succeed())
})
DescribeTable("should work for value",
func(serverType ServerType) {
m := defaultMachine()
m.Spec.Type = serverType
m.Spec.CPUFamily = nil
Expect(k8sClient.Create(context.Background(), m)).To(Succeed())
Expect(m.Spec.Type).To(Equal(serverType))
},
Entry("ENTERPRISE", ServerTypeEnterprise),
Entry("VCPU", ServerTypeVCpu),
)
})
Context("Conditions", func() {
It("should correctly set and get the conditions", func() {
m := defaultMachine()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,24 @@ spec:
ProviderID is the IONOS Cloud provider ID
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
type: string
type:
default: ENTERPRISE
description: Type is the server type of the VM. Can be either ENTERPRISE
or VCPU.
enum:
- ENTERPRISE
- VCPU
type: string
x-kubernetes-validations:
- message: type is immutable
rule: self == oldSelf
required:
- datacenterID
- disk
type: object
x-kubernetes-validations:
- message: cpuFamily must not be specified when using VCPU
rule: self.type != 'VCPU' || !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 @@ -199,6 +199,17 @@ spec:
ProviderID is the IONOS Cloud provider ID
will be in the format ionos://ee090ff2-1eef-48ec-a246-a51a33aa4f3a
type: string
type:
default: ENTERPRISE
description: Type is the server type of the VM. Can be either
ENTERPRISE or VCPU.
enum:
- ENTERPRISE
- VCPU
type: string
x-kubernetes-validations:
- message: type is immutable
rule: self == oldSelf
required:
- datacenterID
- disk
Expand Down
1 change: 1 addition & 0 deletions internal/service/cloud/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ func (*Service) buildServerProperties(
Name: ptr.To(ms.IonosMachine.Name),
Ram: &machineSpec.MemoryMB,
CpuFamily: machineSpec.CPUFamily,
Type: ptr.To(machineSpec.Type.String()),
}

return props
Expand Down
34 changes: 30 additions & 4 deletions internal/service/cloud/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

infrav1 "github.com/ionos-cloud/cluster-api-provider-ionoscloud/api/v1alpha1"
"github.com/ionos-cloud/cluster-api-provider-ionoscloud/internal/ionoscloud/clienttest"
"github.com/ionos-cloud/cluster-api-provider-ionoscloud/internal/util/ptr"
)
Expand Down Expand Up @@ -148,10 +149,10 @@ func (s *serverSuite) TestReconcileServerRequestDoneStateAvailableTurnedOff() {
s.True(requeue)
}

func (s *serverSuite) TestReconcileServerNoRequest() {
func (s *serverSuite) TestReconcileEnterpriseServerNoRequest() {
s.prepareReconcileServerRequestTest()
s.mockGetServerCreationRequestCall().Return([]sdk.Request{}, nil)
s.mockCreateServerCall().Return(&sdk.Server{Id: ptr.To("12345")}, "location/to/server", nil)
s.mockCreateServerCall(infrav1.ServerTypeEnterprise).Return(&sdk.Server{Id: ptr.To("12345")}, "location/to/server", nil)
s.mockListLANsCall().Return(&sdk.Lans{Items: &[]sdk.Lan{{
Id: ptr.To("1"),
Properties: &sdk.LanProperties{
Expand All @@ -166,6 +167,25 @@ func (s *serverSuite) TestReconcileServerNoRequest() {
s.True(requeue)
}

func (s *serverSuite) TestReconcileVCPUServerNoRequest() {
s.prepareReconcileServerRequestTest()
s.mockGetServerCreationRequestCall().Return([]sdk.Request{}, nil)
s.mockCreateServerCall(infrav1.ServerTypeVCpu).Return(&sdk.Server{Id: ptr.To("12345")}, "location/to/server", nil)
s.mockListLANsCall().Return(&sdk.Lans{Items: &[]sdk.Lan{{
Id: ptr.To("1"),
Properties: &sdk.LanProperties{
Name: ptr.To(s.service.lanName(s.clusterScope.Cluster)),
Public: ptr.To(true),
},
}}}, nil)

s.infraMachine.Spec.Type = infrav1.ServerTypeVCpu
requeue, err := s.service.ReconcileServer(s.ctx, s.machineScope)
s.Equal("ionos://12345", ptr.Deref(s.machineScope.IonosMachine.Spec.ProviderID, ""))
s.NoError(err)
s.True(requeue)
}

func (s *serverSuite) prepareReconcileServerRequestTest() {
s.T().Helper()
bootstrapSecret := &corev1.Secret{
Expand Down Expand Up @@ -424,11 +444,11 @@ func (s *serverSuite) mockGetServerDeletionRequestCall(serverID string) *clientt
http.MethodDelete, path.Join(s.service.serversURL(s.machineScope.DatacenterID()), serverID))
}

func (s *serverSuite) mockCreateServerCall() *clienttest.MockClient_CreateServer_Call {
func (s *serverSuite) mockCreateServerCall(serverType infrav1.ServerType) *clienttest.MockClient_CreateServer_Call {
return s.ionosClient.EXPECT().CreateServer(
s.ctx,
s.machineScope.DatacenterID(),
mock.Anything,
mock.MatchedBy(hasServerType(serverType)),
mock.Anything,
lubedacht marked this conversation as resolved.
Show resolved Hide resolved
)
}
Expand Down Expand Up @@ -461,3 +481,9 @@ func (s *serverSuite) examplePostRequest(status string) sdk.Request {
}
return s.exampleRequest(opts)
}

func hasServerType(serverType infrav1.ServerType) func(properties sdk.ServerProperties) bool {
return func(properties sdk.ServerProperties) bool {
return ptr.Deref(properties.Type, "") == serverType.String()
}
}
1 change: 1 addition & 0 deletions internal/service/cloud/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func (s *ServiceTestSuite) SetupTest() {
ID: "3e3e3e3e-3e3e-3e3e-3e3e-3e3e3e3e3e3e",
},
},
Type: infrav1.ServerTypeEnterprise,
},
Status: infrav1.IonosCloudMachineStatus{},
}
Expand Down
Loading