diff --git a/api/v1alpha1/proxmoxmachine_types.go b/api/v1alpha1/proxmoxmachine_types.go index 850e13d..0c26c8a 100644 --- a/api/v1alpha1/proxmoxmachine_types.go +++ b/api/v1alpha1/proxmoxmachine_types.go @@ -204,6 +204,8 @@ type TemplateSource struct { } // VirtualMachineCloneSpec is information used to clone a virtual machine. +// +kubebuilder:validation:XValidation:rule="self.full || !has(self.format)",message="Must set full=true when specifying format" +// +kubebuilder:validation:XValidation:rule="self.full || !has(self.storage)",message="Must set full=true when specifying storage" type VirtualMachineCloneSpec struct { TemplateSource `json:",inline"` @@ -213,7 +215,6 @@ type VirtualMachineCloneSpec struct { // Format for file storage. Only valid for full clone. // +kubebuilder:validation:Enum=raw;qcow2;vmdk - // +kubebuilder:default=raw // +optional Format *TargetFileStorageFormat `json:"format,omitempty"` @@ -578,7 +579,6 @@ type ProxmoxMachine struct { // +kubebuilder:validation:XValidation:rule="[has(self.sourceNode), has(self.templateSelector)].exists_one(c, c)",message="must define either SourceNode with TemplateID, OR TemplateSelector" // +kubebuilder:validation:XValidation:rule="[has(self.templateID), has(self.templateSelector)].exists_one(c, c)",message="must define either SourceNode with TemplateID, OR TemplateSelector." - // +kubebuilder:validation:XValidation:rule="self.full && self.format != ''",message="Must set full=true when specifying format" Spec ProxmoxMachineSpec `json:"spec,omitempty"` Status ProxmoxMachineStatus `json:"status,omitempty"` } diff --git a/api/v1alpha1/proxmoxmachine_types_test.go b/api/v1alpha1/proxmoxmachine_types_test.go index 29f6a17..e6f14fb 100644 --- a/api/v1alpha1/proxmoxmachine_types_test.go +++ b/api/v1alpha1/proxmoxmachine_types_test.go @@ -62,11 +62,29 @@ var _ = Describe("ProxmoxMachine Test", func() { Context("VirtualMachineCloneSpec", func() { It("Should not allow specifying format if full clone is disabled", func() { dm := defaultMachine() + dm.Spec.Format = ptr.To(TargetStorageFormatRaw) dm.Spec.Full = ptr.To(false) Expect(k8sClient.Create(context.Background(), dm)).Should(MatchError(ContainSubstring("Must set full=true when specifying format"))) }) + It("Should not allow specifying storage if full clone is disabled", func() { + dm := defaultMachine() + dm.Spec.Storage = ptr.To("local") + dm.Spec.Full = ptr.To(false) + + Expect(k8sClient.Create(context.Background(), dm)).Should(MatchError(ContainSubstring("Must set full=true when specifying storage"))) + }) + + It("Should allow disabling full clone in absence of format and storage", func() { + dm := defaultMachine() + dm.Spec.Format = nil + dm.Spec.Storage = nil + dm.Spec.Full = ptr.To(false) + + Expect(k8sClient.Create(context.Background(), dm)).Should(Succeed()) + }) + It("Should disallow absence of SourceNode, TemplateID and TemplateSelector", func() { dm := defaultMachine() dm.Spec.TemplateSource.SourceNode = "" diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml index cc8fc96..c9b8cd2 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclusters.yaml @@ -135,7 +135,6 @@ spec: rule: self == oldSelf type: object format: - default: raw description: Format for file storage. Only valid for full clone. enum: @@ -700,6 +699,11 @@ spec: - message: end should be greater than or equal to start rule: self.end >= self.start type: object + x-kubernetes-validations: + - message: Must set full=true when specifying format + rule: self.full || !has(self.format) + - message: Must set full=true when specifying storage + rule: self.full || !has(self.storage) type: object x-kubernetes-validations: - message: Cowardly refusing to deploy cluster without control diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml index 6d5506b..544e59d 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxclustertemplates.yaml @@ -159,7 +159,6 @@ spec: rule: self == oldSelf type: object format: - default: raw description: Format for file storage. Only valid for full clone. enum: @@ -742,6 +741,11 @@ spec: start rule: self.end >= self.start type: object + x-kubernetes-validations: + - message: Must set full=true when specifying format + rule: self.full || !has(self.format) + - message: Must set full=true when specifying storage + rule: self.full || !has(self.storage) type: object x-kubernetes-validations: - message: Cowardly refusing to deploy cluster without diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachines.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachines.yaml index f31a691..ced008b 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachines.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachines.yaml @@ -127,7 +127,6 @@ spec: rule: self == oldSelf type: object format: - default: raw description: Format for file storage. Only valid for full clone. enum: - raw @@ -664,7 +663,9 @@ spec: rule: '[has(self.templateID), has(self.templateSelector)].exists_one(c, c)' - message: Must set full=true when specifying format - rule: self.full && self.format != '' + rule: self.full || !has(self.format) + - message: Must set full=true when specifying storage + rule: self.full || !has(self.storage) status: description: ProxmoxMachineStatus defines the observed state of a ProxmoxMachine. properties: diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachinetemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachinetemplates.yaml index bf26e81..baad08f 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachinetemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachinetemplates.yaml @@ -139,7 +139,6 @@ spec: rule: self == oldSelf type: object format: - default: raw description: Format for file storage. Only valid for full clone. enum: @@ -697,6 +696,11 @@ spec: - message: end should be greater than or equal to start rule: self.end >= self.start type: object + x-kubernetes-validations: + - message: Must set full=true when specifying format + rule: self.full || !has(self.format) + - message: Must set full=true when specifying storage + rule: self.full || !has(self.storage) required: - spec type: object