diff --git a/api/v1beta1/cloudstackmachine_conversion.go b/api/v1beta1/cloudstackmachine_conversion.go index cefa39f7..bc9ab100 100644 --- a/api/v1beta1/cloudstackmachine_conversion.go +++ b/api/v1beta1/cloudstackmachine_conversion.go @@ -25,6 +25,7 @@ import ( func (src *CloudStackMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint dst := dstRaw.(*v1beta3.CloudStackMachine) + if err := Convert_v1beta1_CloudStackMachine_To_v1beta3_CloudStackMachine(src, dst, nil); err != nil { return err } @@ -34,12 +35,22 @@ func (src *CloudStackMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { return err } - if restored.Spec.FailureDomainName != "" { - dst.Spec.FailureDomainName = restored.Spec.FailureDomainName - } - if restored.Spec.UncompressedUserData != nil { - dst.Spec.UncompressedUserData = restored.Spec.UncompressedUserData + dst.Spec.FailureDomainName = restored.Spec.FailureDomainName + dst.Spec.UncompressedUserData = restored.Spec.UncompressedUserData + + // Don't bother converting empty disk offering objects + if restored.Spec.DiskOffering.MountPath != "" { + dst.Spec.DiskOffering = &v1beta3.CloudStackResourceDiskOffering{ + CustomSize: restored.Spec.DiskOffering.CustomSize, + MountPath: restored.Spec.DiskOffering.MountPath, + Device: restored.Spec.DiskOffering.Device, + Filesystem: restored.Spec.DiskOffering.Filesystem, + Label: restored.Spec.DiskOffering.Label, + } + dst.Spec.DiskOffering.ID = restored.Spec.DiskOffering.ID + dst.Spec.DiskOffering.Name = restored.Spec.DiskOffering.Name } + if restored.Status.Status != nil { dst.Status.Status = restored.Status.Status } @@ -51,6 +62,7 @@ func (src *CloudStackMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint func (dst *CloudStackMachine) ConvertFrom(srcRaw conversion.Hub) error { // nolint src := srcRaw.(*v1beta3.CloudStackMachine) + if err := Convert_v1beta3_CloudStackMachine_To_v1beta1_CloudStackMachine(src, dst, nil); err != nil { return err } @@ -62,6 +74,10 @@ func (dst *CloudStackMachine) ConvertFrom(srcRaw conversion.Hub) error { // noli return nil } +func Convert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in *CloudStackMachineSpec, out *v1beta3.CloudStackMachineSpec, scope machineryconversion.Scope) error { // nolint + return autoConvert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in, out, scope) +} + func Convert_v1beta3_CloudStackMachineSpec_To_v1beta1_CloudStackMachineSpec(in *v1beta3.CloudStackMachineSpec, out *CloudStackMachineSpec, s machineryconversion.Scope) error { // nolint return autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta1_CloudStackMachineSpec(in, out, s) } diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go index 16c82c57..3a2b19cb 100644 --- a/api/v1beta1/zz_generated.conversion.go +++ b/api/v1beta1/zz_generated.conversion.go @@ -128,11 +128,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*CloudStackMachineSpec)(nil), (*v1beta3.CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(a.(*CloudStackMachineSpec), b.(*v1beta3.CloudStackMachineSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*CloudStackMachineStateChecker)(nil), (*v1beta3.CloudStackMachineStateChecker)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_CloudStackMachineStateChecker_To_v1beta3_CloudStackMachineStateChecker(a.(*CloudStackMachineStateChecker), b.(*v1beta3.CloudStackMachineStateChecker), scope) }); err != nil { @@ -258,6 +253,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*CloudStackMachineSpec)(nil), (*v1beta3.CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(a.(*CloudStackMachineSpec), b.(*v1beta3.CloudStackMachineSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*CloudStackMachineTemplateSpec)(nil), (*v1beta3.CloudStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_CloudStackMachineTemplateSpec_To_v1beta3_CloudStackMachineTemplateSpec(a.(*CloudStackMachineTemplateSpec), b.(*v1beta3.CloudStackMachineTemplateSpec), scope) }); err != nil { @@ -617,9 +617,7 @@ func autoConvert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec( if err := Convert_v1beta1_CloudStackResourceIdentifier_To_v1beta3_CloudStackResourceIdentifier(&in.Template, &out.Template, s); err != nil { return err } - if err := Convert_v1beta1_CloudStackResourceDiskOffering_To_v1beta3_CloudStackResourceDiskOffering(&in.DiskOffering, &out.DiskOffering, s); err != nil { - return err - } + // WARNING: in.DiskOffering requires manual conversion: inconvertible types (./api/v1beta1.CloudStackResourceDiskOffering vs *sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3.CloudStackResourceDiskOffering) out.SSHKey = in.SSHKey out.Details = *(*map[string]string)(unsafe.Pointer(&in.Details)) out.AffinityGroupIDs = *(*[]string)(unsafe.Pointer(&in.AffinityGroupIDs)) @@ -632,11 +630,6 @@ func autoConvert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec( return nil } -// Convert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec is an autogenerated conversion function. -func Convert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in *CloudStackMachineSpec, out *v1beta3.CloudStackMachineSpec, s conversion.Scope) error { - return autoConvert_v1beta1_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in, out, s) -} - func autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta1_CloudStackMachineSpec(in *v1beta3.CloudStackMachineSpec, out *CloudStackMachineSpec, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID @@ -647,9 +640,7 @@ func autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta1_CloudStackMachineSpec( if err := Convert_v1beta3_CloudStackResourceIdentifier_To_v1beta1_CloudStackResourceIdentifier(&in.Template, &out.Template, s); err != nil { return err } - if err := Convert_v1beta3_CloudStackResourceDiskOffering_To_v1beta1_CloudStackResourceDiskOffering(&in.DiskOffering, &out.DiskOffering, s); err != nil { - return err - } + // WARNING: in.DiskOffering requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3.CloudStackResourceDiskOffering vs ./api/v1beta1.CloudStackResourceDiskOffering) out.SSHKey = in.SSHKey out.Details = *(*map[string]string)(unsafe.Pointer(&in.Details)) out.AffinityGroupIDs = *(*[]string)(unsafe.Pointer(&in.AffinityGroupIDs)) diff --git a/api/v1beta2/cloudstackmachine_conversion.go b/api/v1beta2/cloudstackmachine_conversion.go index 43225d52..2497b705 100644 --- a/api/v1beta2/cloudstackmachine_conversion.go +++ b/api/v1beta2/cloudstackmachine_conversion.go @@ -17,16 +17,57 @@ limitations under the License. package v1beta2 import ( + machineryconversion "k8s.io/apimachinery/pkg/conversion" "sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3" + utilconversion "sigs.k8s.io/cluster-api/util/conversion" "sigs.k8s.io/controller-runtime/pkg/conversion" ) -func (src *CloudStackMachine) ConvertTo(dstRaw conversion.Hub) error { // nolint +func (src *CloudStackMachine) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*v1beta3.CloudStackMachine) - return Convert_v1beta2_CloudStackMachine_To_v1beta3_CloudStackMachine(src, dst, nil) + + if err := Convert_v1beta2_CloudStackMachine_To_v1beta3_CloudStackMachine(src, dst, nil); err != nil { + return err + } + + // Manually restore data + restored := &v1beta3.CloudStackMachine{} + if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { + return err + } + // Don't bother converting empty disk offering objects + if restored.Spec.DiskOffering.MountPath != "" { + dst.Spec.DiskOffering = &v1beta3.CloudStackResourceDiskOffering{ + CustomSize: restored.Spec.DiskOffering.CustomSize, + MountPath: restored.Spec.DiskOffering.MountPath, + Device: restored.Spec.DiskOffering.Device, + Filesystem: restored.Spec.DiskOffering.Filesystem, + Label: restored.Spec.DiskOffering.Label, + } + dst.Spec.DiskOffering.ID = restored.Spec.DiskOffering.ID + dst.Spec.DiskOffering.Name = restored.Spec.DiskOffering.Name + } + return nil } func (dst *CloudStackMachine) ConvertFrom(srcRaw conversion.Hub) error { // nolint src := srcRaw.(*v1beta3.CloudStackMachine) - return Convert_v1beta3_CloudStackMachine_To_v1beta2_CloudStackMachine(src, dst, nil) + + if err := Convert_v1beta3_CloudStackMachine_To_v1beta2_CloudStackMachine(src, dst, nil); err != nil { + return err + } + + // Preserve Hub data on down-conversion + if err := utilconversion.MarshalData(src, dst); err != nil { + return err + } + return nil +} + +func Convert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(in *v1beta3.CloudStackMachineSpec, out *CloudStackMachineSpec, s machineryconversion.Scope) error { // nolint + return autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(in, out, s) +} + +func Convert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in *CloudStackMachineSpec, out *v1beta3.CloudStackMachineSpec, s machineryconversion.Scope) error { // nolint + return autoConvert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in, out, s) } diff --git a/api/v1beta2/zz_generated.conversion.go b/api/v1beta2/zz_generated.conversion.go index 026a8bd5..3e25ef61 100644 --- a/api/v1beta2/zz_generated.conversion.go +++ b/api/v1beta2/zz_generated.conversion.go @@ -213,16 +213,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*CloudStackMachineSpec)(nil), (*v1beta3.CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(a.(*CloudStackMachineSpec), b.(*v1beta3.CloudStackMachineSpec), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1beta3.CloudStackMachineSpec)(nil), (*CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(a.(*v1beta3.CloudStackMachineSpec), b.(*CloudStackMachineSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*CloudStackMachineStateChecker)(nil), (*v1beta3.CloudStackMachineStateChecker)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_CloudStackMachineStateChecker_To_v1beta3_CloudStackMachineStateChecker(a.(*CloudStackMachineStateChecker), b.(*v1beta3.CloudStackMachineStateChecker), scope) }); err != nil { @@ -353,6 +343,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*CloudStackMachineSpec)(nil), (*v1beta3.CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(a.(*CloudStackMachineSpec), b.(*v1beta3.CloudStackMachineSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*CloudStackMachineTemplateSpec)(nil), (*v1beta3.CloudStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_CloudStackMachineTemplateSpec_To_v1beta3_CloudStackMachineTemplateSpec(a.(*CloudStackMachineTemplateSpec), b.(*v1beta3.CloudStackMachineTemplateSpec), scope) }); err != nil { @@ -363,6 +358,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta3.CloudStackMachineSpec)(nil), (*CloudStackMachineSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(a.(*v1beta3.CloudStackMachineSpec), b.(*CloudStackMachineSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta3.CloudStackMachineTemplateSpec)(nil), (*CloudStackMachineTemplateSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta3_CloudStackMachineTemplateSpec_To_v1beta2_CloudStackMachineTemplateSpec(a.(*v1beta3.CloudStackMachineTemplateSpec), b.(*CloudStackMachineTemplateSpec), scope) }); err != nil { @@ -869,7 +869,17 @@ func Convert_v1beta3_CloudStackMachine_To_v1beta2_CloudStackMachine(in *v1beta3. func autoConvert_v1beta2_CloudStackMachineList_To_v1beta3_CloudStackMachineList(in *CloudStackMachineList, out *v1beta3.CloudStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]v1beta3.CloudStackMachine)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1beta3.CloudStackMachine, len(*in)) + for i := range *in { + if err := Convert_v1beta2_CloudStackMachine_To_v1beta3_CloudStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -880,7 +890,17 @@ func Convert_v1beta2_CloudStackMachineList_To_v1beta3_CloudStackMachineList(in * func autoConvert_v1beta3_CloudStackMachineList_To_v1beta2_CloudStackMachineList(in *v1beta3.CloudStackMachineList, out *CloudStackMachineList, s conversion.Scope) error { out.ListMeta = in.ListMeta - out.Items = *(*[]CloudStackMachine)(unsafe.Pointer(&in.Items)) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CloudStackMachine, len(*in)) + for i := range *in { + if err := Convert_v1beta3_CloudStackMachine_To_v1beta2_CloudStackMachine(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } return nil } @@ -899,9 +919,7 @@ func autoConvert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec( if err := Convert_v1beta2_CloudStackResourceIdentifier_To_v1beta3_CloudStackResourceIdentifier(&in.Template, &out.Template, s); err != nil { return err } - if err := Convert_v1beta2_CloudStackResourceDiskOffering_To_v1beta3_CloudStackResourceDiskOffering(&in.DiskOffering, &out.DiskOffering, s); err != nil { - return err - } + // WARNING: in.DiskOffering requires manual conversion: inconvertible types (./api/v1beta2.CloudStackResourceDiskOffering vs *sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3.CloudStackResourceDiskOffering) out.SSHKey = in.SSHKey out.Details = *(*map[string]string)(unsafe.Pointer(&in.Details)) out.AffinityGroupIDs = *(*[]string)(unsafe.Pointer(&in.AffinityGroupIDs)) @@ -913,11 +931,6 @@ func autoConvert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec( return nil } -// Convert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec is an autogenerated conversion function. -func Convert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in *CloudStackMachineSpec, out *v1beta3.CloudStackMachineSpec, s conversion.Scope) error { - return autoConvert_v1beta2_CloudStackMachineSpec_To_v1beta3_CloudStackMachineSpec(in, out, s) -} - func autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(in *v1beta3.CloudStackMachineSpec, out *CloudStackMachineSpec, s conversion.Scope) error { out.Name = in.Name out.ID = in.ID @@ -928,9 +941,7 @@ func autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec( if err := Convert_v1beta3_CloudStackResourceIdentifier_To_v1beta2_CloudStackResourceIdentifier(&in.Template, &out.Template, s); err != nil { return err } - if err := Convert_v1beta3_CloudStackResourceDiskOffering_To_v1beta2_CloudStackResourceDiskOffering(&in.DiskOffering, &out.DiskOffering, s); err != nil { - return err - } + // WARNING: in.DiskOffering requires manual conversion: inconvertible types (*sigs.k8s.io/cluster-api-provider-cloudstack/api/v1beta3.CloudStackResourceDiskOffering vs ./api/v1beta2.CloudStackResourceDiskOffering) out.SSHKey = in.SSHKey out.Details = *(*map[string]string)(unsafe.Pointer(&in.Details)) out.AffinityGroupIDs = *(*[]string)(unsafe.Pointer(&in.AffinityGroupIDs)) @@ -942,11 +953,6 @@ func autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec( return nil } -// Convert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec is an autogenerated conversion function. -func Convert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(in *v1beta3.CloudStackMachineSpec, out *CloudStackMachineSpec, s conversion.Scope) error { - return autoConvert_v1beta3_CloudStackMachineSpec_To_v1beta2_CloudStackMachineSpec(in, out, s) -} - func autoConvert_v1beta2_CloudStackMachineStateChecker_To_v1beta3_CloudStackMachineStateChecker(in *CloudStackMachineStateChecker, out *v1beta3.CloudStackMachineStateChecker, s conversion.Scope) error { out.ObjectMeta = in.ObjectMeta if err := Convert_v1beta2_CloudStackMachineStateCheckerSpec_To_v1beta3_CloudStackMachineStateCheckerSpec(&in.Spec, &out.Spec, s); err != nil { diff --git a/api/v1beta3/cloudstackcluster_webhook.go b/api/v1beta3/cloudstackcluster_webhook.go index 1e7a5feb..083ca39b 100644 --- a/api/v1beta3/cloudstackcluster_webhook.go +++ b/api/v1beta3/cloudstackcluster_webhook.go @@ -38,9 +38,13 @@ func (r *CloudStackCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters,verbs=create;update,versions=v1beta3,name=mcloudstackcluster.kb.io,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters,versions=v1beta3,name=validation.cloudstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters,versions=v1beta3,name=default.cloudstackcluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &CloudStackCluster{} +var ( + _ webhook.Defaulter = &CloudStackCluster{} + _ webhook.Validator = &CloudStackCluster{} +) // Default implements webhook.Defaulter so a webhook will be registered for the type func (r *CloudStackCluster) Default() { @@ -48,10 +52,6 @@ func (r *CloudStackCluster) Default() { // No defaulted values supported yet. } -// +kubebuilder:webhook:name=vcloudstackcluster.kb.io,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackclusters,versions=v1beta3,verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster,mutating=false,failurePolicy=fail,sideEffects=None,admissionReviewVersions=v1;v1beta1 - -var _ webhook.Validator = &CloudStackCluster{} - // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (r *CloudStackCluster) ValidateCreate() error { cloudstackclusterlog.V(1).Info("entered validate create webhook", "api resource name", r.Name) diff --git a/api/v1beta3/cloudstackmachine_types.go b/api/v1beta3/cloudstackmachine_types.go index 22afe0ce..de3b4266 100644 --- a/api/v1beta3/cloudstackmachine_types.go +++ b/api/v1beta3/cloudstackmachine_types.go @@ -53,7 +53,7 @@ type CloudStackMachineSpec struct { // CloudStack disk offering to use. // +optional - DiskOffering CloudStackResourceDiskOffering `json:"diskOffering,omitempty"` + DiskOffering *CloudStackResourceDiskOffering `json:"diskOffering,omitempty"` // CloudStack ssh key to use. // +optional diff --git a/api/v1beta3/cloudstackmachine_webhook.go b/api/v1beta3/cloudstackmachine_webhook.go index 5f55ddf0..a2e39411 100644 --- a/api/v1beta3/cloudstackmachine_webhook.go +++ b/api/v1beta3/cloudstackmachine_webhook.go @@ -38,9 +38,13 @@ func (r *CloudStackMachine) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -//+kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines,verbs=create;update,versions=v1beta3,name=mcloudstackmachine.kb.io,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines,versions=v1beta3,name=validation.cloudstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines,versions=v1beta3,name=default.cloudstackmachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &CloudStackMachine{} +var ( + _ webhook.Defaulter = &CloudStackMachine{} + _ webhook.Validator = &CloudStackMachine{} +) // Default implements webhook.Defaulter so a webhook will be registered for the type func (r *CloudStackMachine) Default() { @@ -48,10 +52,6 @@ func (r *CloudStackMachine) Default() { // No defaulted values supported yet. } -//+kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines,verbs=create;update,versions=v1beta3,name=vcloudstackmachine.kb.io,admissionReviewVersions=v1;v1beta1 - -var _ webhook.Validator = &CloudStackMachine{} - // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (r *CloudStackMachine) ValidateCreate() error { cloudstackmachinelog.V(1).Info("entered validate create webhook", "api resource name", r.Name) @@ -60,7 +60,7 @@ func (r *CloudStackMachine) ValidateCreate() error { errorList = webhookutil.EnsureAtLeastOneFieldExists(r.Spec.Offering.ID, r.Spec.Offering.Name, "Offering", errorList) errorList = webhookutil.EnsureAtLeastOneFieldExists(r.Spec.Template.ID, r.Spec.Template.Name, "Template", errorList) - if len(r.Spec.DiskOffering.ID) > 0 || len(r.Spec.DiskOffering.Name) > 0 { + if r.Spec.DiskOffering != nil && (len(r.Spec.DiskOffering.ID) > 0 || len(r.Spec.DiskOffering.Name) > 0) { errorList = webhookutil.EnsureIntFieldsAreNotNegative(r.Spec.DiskOffering.CustomSize, "customSizeInGB", errorList) } @@ -81,13 +81,15 @@ func (r *CloudStackMachine) ValidateUpdate(old runtime.Object) error { errorList = webhookutil.EnsureEqualStrings(r.Spec.Offering.ID, oldSpec.Offering.ID, "offering", errorList) errorList = webhookutil.EnsureEqualStrings(r.Spec.Offering.Name, oldSpec.Offering.Name, "offering", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.ID, oldSpec.DiskOffering.ID, "diskOffering", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Name, oldSpec.DiskOffering.Name, "diskOffering", errorList) - errorList = webhookutil.EnsureIntFieldsAreNotNegative(r.Spec.DiskOffering.CustomSize, "customSizeInGB", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.MountPath, oldSpec.DiskOffering.MountPath, "mountPath", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Device, oldSpec.DiskOffering.Device, "device", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Filesystem, oldSpec.DiskOffering.Filesystem, "filesystem", errorList) - errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Label, oldSpec.DiskOffering.Label, "label", errorList) + if r.Spec.DiskOffering != nil { + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.ID, oldSpec.DiskOffering.ID, "diskOffering", errorList) + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Name, oldSpec.DiskOffering.Name, "diskOffering", errorList) + errorList = webhookutil.EnsureIntFieldsAreNotNegative(r.Spec.DiskOffering.CustomSize, "customSizeInGB", errorList) + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.MountPath, oldSpec.DiskOffering.MountPath, "mountPath", errorList) + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Device, oldSpec.DiskOffering.Device, "device", errorList) + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Filesystem, oldSpec.DiskOffering.Filesystem, "filesystem", errorList) + errorList = webhookutil.EnsureEqualStrings(r.Spec.DiskOffering.Label, oldSpec.DiskOffering.Label, "label", errorList) + } errorList = webhookutil.EnsureEqualStrings(r.Spec.SSHKey, oldSpec.SSHKey, "sshkey", errorList) errorList = webhookutil.EnsureEqualStrings(r.Spec.Template.ID, oldSpec.Template.ID, "template", errorList) errorList = webhookutil.EnsureEqualStrings(r.Spec.Template.Name, oldSpec.Template.Name, "template", errorList) diff --git a/api/v1beta3/cloudstackmachinetemplate_webhook.go b/api/v1beta3/cloudstackmachinetemplate_webhook.go index 430d17b6..e148a335 100644 --- a/api/v1beta3/cloudstackmachinetemplate_webhook.go +++ b/api/v1beta3/cloudstackmachinetemplate_webhook.go @@ -39,9 +39,13 @@ func (r *CloudStackMachineTemplate) SetupWebhookWithManager(mgr ctrl.Manager) er Complete() } -// +kubebuilder:webhook:path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate,mutating=true,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachinetemplates,verbs=create;update,versions=v1beta3,name=mcloudstackmachinetemplate.kb.io,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachinetemplates,versions=v1beta3,name=validation.cloudstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachinetemplates,versions=v1beta3,name=default.cloudstackmachinetemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 -var _ webhook.Defaulter = &CloudStackMachineTemplate{} +var ( + _ webhook.Defaulter = &CloudStackMachineTemplate{} + _ webhook.Validator = &CloudStackMachineTemplate{} +) // Default implements webhook.Defaulter so a webhook will be registered for the type func (r *CloudStackMachineTemplate) Default() { @@ -49,10 +53,6 @@ func (r *CloudStackMachineTemplate) Default() { // No defaulted values supported yet. } -// +kubebuilder:webhook:path=/validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate,mutating=false,failurePolicy=fail,sideEffects=None,groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachinetemplates,verbs=create;update,versions=v1beta3,name=vcloudstackmachinetemplate.kb.io,admissionReviewVersions=v1;v1beta1 - -var _ webhook.Validator = &CloudStackMachineTemplate{} - // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (r *CloudStackMachineTemplate) ValidateCreate() error { cloudstackmachinetemplatelog.V(1).Info("entered validate create webhook", "api resource name", r.Name) @@ -94,8 +94,10 @@ func (r *CloudStackMachineTemplate) ValidateUpdate(old runtime.Object) error { errorList := field.ErrorList(nil) errorList = webhookutil.EnsureEqualStrings(spec.Offering.ID, oldSpec.Offering.ID, "offering", errorList) errorList = webhookutil.EnsureEqualStrings(spec.Offering.Name, oldSpec.Offering.Name, "offering", errorList) - errorList = webhookutil.EnsureEqualStrings(spec.DiskOffering.ID, oldSpec.DiskOffering.ID, "diskOffering", errorList) - errorList = webhookutil.EnsureEqualStrings(spec.DiskOffering.Name, oldSpec.DiskOffering.Name, "diskOffering", errorList) + if spec.DiskOffering != nil { + errorList = webhookutil.EnsureEqualStrings(spec.DiskOffering.ID, oldSpec.DiskOffering.ID, "diskOffering", errorList) + errorList = webhookutil.EnsureEqualStrings(spec.DiskOffering.Name, oldSpec.DiskOffering.Name, "diskOffering", errorList) + } errorList = webhookutil.EnsureEqualStrings(spec.SSHKey, oldSpec.SSHKey, "sshkey", errorList) errorList = webhookutil.EnsureEqualStrings(spec.Template.ID, oldSpec.Template.ID, "template", errorList) errorList = webhookutil.EnsureEqualStrings(spec.Template.Name, oldSpec.Template.Name, "template", errorList) diff --git a/api/v1beta3/cloudstackmachinetemplate_webhook_test.go b/api/v1beta3/cloudstackmachinetemplate_webhook_test.go index a6d03446..a5b5f679 100644 --- a/api/v1beta3/cloudstackmachinetemplate_webhook_test.go +++ b/api/v1beta3/cloudstackmachinetemplate_webhook_test.go @@ -43,7 +43,7 @@ var _ = Describe("CloudStackMachineTemplate webhook", func() { }) It("Should accept a CloudStackMachineTemplate when missing the VM Disk Offering attribute", func() { - dummies.CSMachineTemplate1.Spec.Template.Spec.DiskOffering = infrav1.CloudStackResourceDiskOffering{ + dummies.CSMachineTemplate1.Spec.Template.Spec.DiskOffering = &infrav1.CloudStackResourceDiskOffering{ CloudStackResourceIdentifier: infrav1.CloudStackResourceIdentifier{Name: "", ID: ""}, } Expect(k8sClient.Create(ctx, dummies.CSMachineTemplate1)).Should(Succeed()) @@ -74,7 +74,7 @@ var _ = Describe("CloudStackMachineTemplate webhook", func() { }) It("should reject VM disk offering updates to the CloudStackMachineTemplate", func() { - dummies.CSMachineTemplate1.Spec.Template.Spec.DiskOffering = infrav1.CloudStackResourceDiskOffering{ + dummies.CSMachineTemplate1.Spec.Template.Spec.DiskOffering = &infrav1.CloudStackResourceDiskOffering{ CloudStackResourceIdentifier: infrav1.CloudStackResourceIdentifier{Name: "DiskOffering2"}} Ω(k8sClient.Update(ctx, dummies.CSMachineTemplate1)). Should(MatchError(MatchRegexp(forbiddenRegex, "diskOffering"))) diff --git a/api/v1beta3/zz_generated.deepcopy.go b/api/v1beta3/zz_generated.deepcopy.go index 993a974a..bb2e948f 100644 --- a/api/v1beta3/zz_generated.deepcopy.go +++ b/api/v1beta3/zz_generated.deepcopy.go @@ -468,7 +468,11 @@ func (in *CloudStackMachineSpec) DeepCopyInto(out *CloudStackMachineSpec) { } out.Offering = in.Offering out.Template = in.Template - out.DiskOffering = in.DiskOffering + if in.DiskOffering != nil { + in, out := &in.DiskOffering, &out.DiskOffering + *out = new(CloudStackResourceDiskOffering) + **out = **in + } if in.Details != nil { in, out := &in.Details, &out.Details *out = make(map[string]string, len(*in)) diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index aab3da7e..104cb915 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -14,7 +14,8 @@ webhooks: namespace: system path: /mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster failurePolicy: Fail - name: mcloudstackcluster.kb.io + matchPolicy: Equivalent + name: default.cloudstackcluster.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io @@ -35,7 +36,8 @@ webhooks: namespace: system path: /mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine failurePolicy: Fail - name: mcloudstackmachine.kb.io + matchPolicy: Equivalent + name: default.cloudstackmachine.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io @@ -56,7 +58,8 @@ webhooks: namespace: system path: /mutate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate failurePolicy: Fail - name: mcloudstackmachinetemplate.kb.io + matchPolicy: Equivalent + name: default.cloudstackmachinetemplate.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io @@ -84,7 +87,8 @@ webhooks: namespace: system path: /validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackcluster failurePolicy: Fail - name: vcloudstackcluster.kb.io + matchPolicy: Equivalent + name: validation.cloudstackcluster.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io @@ -105,7 +109,8 @@ webhooks: namespace: system path: /validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachine failurePolicy: Fail - name: vcloudstackmachine.kb.io + matchPolicy: Equivalent + name: validation.cloudstackmachine.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io @@ -126,7 +131,8 @@ webhooks: namespace: system path: /validate-infrastructure-cluster-x-k8s-io-v1beta3-cloudstackmachinetemplate failurePolicy: Fail - name: vcloudstackmachinetemplate.kb.io + matchPolicy: Equivalent + name: validation.cloudstackmachinetemplate.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io diff --git a/pkg/cloud/instance.go b/pkg/cloud/instance.go index f7564d3c..095eb394 100644 --- a/pkg/cloud/instance.go +++ b/pkg/cloud/instance.go @@ -154,6 +154,9 @@ func (c *client) ResolveTemplate( // disk offering name matches name provided in spec. // If disk offering ID is not provided, the disk offering name is used to retrieve disk offering ID. func (c *client) ResolveDiskOffering(csMachine *infrav1.CloudStackMachine, zoneID string) (diskOfferingID string, retErr error) { + if csMachine.Spec.DiskOffering == nil { + return "", nil + } diskOfferingID = csMachine.Spec.DiskOffering.ID if len(csMachine.Spec.DiskOffering.Name) > 0 { diskID, count, err := c.cs.DiskOffering.GetDiskOfferingID(csMachine.Spec.DiskOffering.Name, cloudstack.WithZone(zoneID), cloudstack.WithProject(c.user.Project.ID)) @@ -334,8 +337,10 @@ func (c *client) DeployVM( setIfNotEmpty(csMachine.Name, p.SetName) setIfNotEmpty(capiMachine.Name, p.SetDisplayname) setIfNotEmpty(diskOfferingID, p.SetDiskofferingid) + if csMachine.Spec.DiskOffering != nil { + setIntIfPositive(csMachine.Spec.DiskOffering.CustomSize, p.SetSize) + } setIfNotEmpty(c.user.Project.ID, p.SetProjectid) - setIntIfPositive(csMachine.Spec.DiskOffering.CustomSize, p.SetSize) setIfNotEmpty(csMachine.Spec.SSHKey, p.SetKeypair) diff --git a/pkg/cloud/instance_test.go b/pkg/cloud/instance_test.go index 839c0c1f..71431bf2 100644 --- a/pkg/cloud/instance_test.go +++ b/pkg/cloud/instance_test.go @@ -653,7 +653,7 @@ var _ = Describe("Instance", func() { dummies.CSMachine1.Spec.Template.ID = "" dummies.CSMachine1.Spec.Offering.Name = "offering" dummies.CSMachine1.Spec.Template.Name = "template" - dummies.CSMachine1.Spec.DiskOffering = infrav1.CloudStackResourceDiskOffering{} + dummies.CSMachine1.Spec.DiskOffering = &infrav1.CloudStackResourceDiskOffering{} sos.EXPECT().GetServiceOfferingByName(dummies.CSMachine1.Spec.Offering.Name, gomock.Any()).Return(&cloudstack.ServiceOffering{ Id: offeringFakeID, diff --git a/test/dummies/v1beta3/vars.go b/test/dummies/v1beta3/vars.go index e633abf5..52480350 100644 --- a/test/dummies/v1beta3/vars.go +++ b/test/dummies/v1beta3/vars.go @@ -82,7 +82,7 @@ var ( // Declare exported dummy vars. EndPointHost string EndPointPort int32 CSConf *simpleyaml.Yaml - DiskOffering infrav1.CloudStackResourceDiskOffering + DiskOffering *infrav1.CloudStackResourceDiskOffering BootstrapSecret *corev1.Secret BootstrapSecretName string CSMachineOwner *fakes.CloudStackMachineOwner @@ -118,7 +118,7 @@ func SetDummyVars() { } func SetDiskOfferingVars() { - DiskOffering = infrav1.CloudStackResourceDiskOffering{CloudStackResourceIdentifier: infrav1.CloudStackResourceIdentifier{Name: "Small"}, + DiskOffering = &infrav1.CloudStackResourceDiskOffering{CloudStackResourceIdentifier: infrav1.CloudStackResourceIdentifier{Name: "Small"}, MountPath: "/data", Device: "/dev/vdb", Filesystem: "ext4", @@ -232,7 +232,7 @@ func SetDummyCSMachineVars() { Offering: infrav1.CloudStackResourceIdentifier{ Name: GetYamlVal("CLOUDSTACK_CONTROL_PLANE_MACHINE_OFFERING"), }, - DiskOffering: infrav1.CloudStackResourceDiskOffering{ + DiskOffering: &infrav1.CloudStackResourceDiskOffering{ CloudStackResourceIdentifier: infrav1.CloudStackResourceIdentifier{ Name: "DiskOffering", },