From a8adc6855705cadab7ebd8e398ad543764c6e0c8 Mon Sep 17 00:00:00 2001 From: Marcin Franczyk Date: Thu, 15 Oct 2020 13:47:13 +0200 Subject: [PATCH] allow to customize VM devices Signed-off-by: Marcin Franczyk --- .../templates/machine-class.yaml | 4 + charts/internal/machine-class/values.yaml | 5 + hack/api-reference/api.md | 81 +++++++++++ pkg/admission/validator/shoot.go | 47 ++++--- pkg/apis/kubevirt/types_worker.go | 15 +- pkg/apis/kubevirt/v1alpha1/types_worker.go | 19 +++ .../v1alpha1/zz_generated.conversion.go | 38 +++++ .../v1alpha1/zz_generated.deepcopy.go | 33 +++++ pkg/apis/kubevirt/validation/shoot.go | 3 + pkg/apis/kubevirt/validation/shoot_test.go | 14 ++ pkg/apis/kubevirt/validation/worker.go | 44 +++++- pkg/apis/kubevirt/validation/worker_test.go | 130 ++++++++++++++++-- pkg/apis/kubevirt/zz_generated.deepcopy.go | 33 +++++ pkg/controller/worker/machines.go | 6 +- pkg/controller/worker/machines_test.go | 81 +++++++++++ pkg/mock/client/mocks.go | 59 ++++---- pkg/mock/kubevirt/mocks.go | 59 ++++---- pkg/mock/worker/mocks.go | 27 ++-- 18 files changed, 588 insertions(+), 110 deletions(-) diff --git a/charts/internal/machine-class/templates/machine-class.yaml b/charts/internal/machine-class/templates/machine-class.yaml index a5490065..9b878f1b 100644 --- a/charts/internal/machine-class/templates/machine-class.yaml +++ b/charts/internal/machine-class/templates/machine-class.yaml @@ -24,6 +24,10 @@ providerSpec: resources: {{ toYaml $machineClass.resources | indent 4 }} {{- end }} +{{- if $machineClass.devices }} + devices: +{{ toYaml $machineClass.devices | indent 4 }} +{{- end }} {{- if $machineClass.rootVolume }} rootVolume: {{ toYaml $machineClass.rootVolume | indent 4 }} diff --git a/charts/internal/machine-class/values.yaml b/charts/internal/machine-class/values.yaml index 4163abb1..b6ba140c 100644 --- a/charts/internal/machine-class/values.yaml +++ b/charts/internal/machine-class/values.yaml @@ -10,6 +10,11 @@ machineClasses: cpu: "300m" memory: "4Gi" overcommitGuestOverhead: true + devices: + disks: + - name: "root-disk" + cache: "none" + networkInterfaceMultiQueue: true rootVolume: pvc: storageClassName: standard diff --git a/hack/api-reference/api.md b/hack/api-reference/api.md index d0bbddf4..959758a9 100644 --- a/hack/api-reference/api.md +++ b/hack/api-reference/api.md @@ -205,6 +205,20 @@ string +devices
+ + +Devices + + + + +(Optional) +

Devices allows to customize devices attached to KubeVirt VM

+ + + + cpu
kubevirt.io/client-go/api/v1.CPU @@ -375,6 +389,73 @@ map[string]bool +

Devices +

+

+(Appears on: +WorkerConfig) +

+

+

Devices allows to fine-tune devices attached to KubeVirt VM

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+disks
+ +[]kubevirt.io/client-go/api/v1.Disk + +
+(Optional) +

Disks allows to customize disks attached to KubeVirt VM

+
+rng
+ +kubevirt.io/client-go/api/v1.Rng + +
+(Optional) +

Whether to have random number generator from host

+
+blockMultiQueue
+ +bool + +
+(Optional) +

Whether or not to enable virtio multi-queue for block devices

+
+networkInterfaceMultiqueue
+ +bool + +
+(Optional) +

If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature

+

InfrastructureStatus

diff --git a/pkg/admission/validator/shoot.go b/pkg/admission/validator/shoot.go index a8b1cf52..682f8506 100644 --- a/pkg/admission/validator/shoot.go +++ b/pkg/admission/validator/shoot.go @@ -93,13 +93,18 @@ var ( workerConfigPath = func(index int) *field.Path { return workersPath.Index(index).Child("providerConfig") } ) +type workerConfigContext struct { + workerConfig *apiskubevirt.WorkerConfig + dataVolumes []core.DataVolume +} + type validationContext struct { - shoot *core.Shoot - infrastructureConfig *apiskubevirt.InfrastructureConfig - controlPlaneConfig *apiskubevirt.ControlPlaneConfig - workerConfigs []*apiskubevirt.WorkerConfig - cloudProfile *gardencorev1beta1.CloudProfile - cloudProfileConfig *apiskubevirt.CloudProfileConfig + shoot *core.Shoot + infrastructureConfig *apiskubevirt.InfrastructureConfig + controlPlaneConfig *apiskubevirt.ControlPlaneConfig + workerConfigsContexts []*workerConfigContext + cloudProfile *gardencorev1beta1.CloudProfile + cloudProfileConfig *apiskubevirt.CloudProfileConfig } func (s *shoot) validateContext(valContext *validationContext) field.ErrorList { @@ -111,8 +116,8 @@ func (s *shoot) validateContext(valContext *validationContext) field.ErrorList { allErrors = append(allErrors, validation.ValidateInfrastructureConfig(valContext.infrastructureConfig, infrastructureConfigPath)...) allErrors = append(allErrors, validation.ValidateControlPlaneConfig(valContext.controlPlaneConfig, controlPlaneConfigPath)...) allErrors = append(allErrors, validation.ValidateWorkers(valContext.shoot.Spec.Provider.Workers, workersPath)...) - for i, workerConfig := range valContext.workerConfigs { - allErrors = append(allErrors, validation.ValidateWorkerConfig(workerConfig, workerConfigPath(i))...) + for i, workerConfigContext := range valContext.workerConfigsContexts { + allErrors = append(allErrors, validation.ValidateWorkerConfig(workerConfigContext.workerConfig, workerConfigContext.dataVolumes, workerConfigPath(i))...) } return allErrors @@ -158,8 +163,10 @@ func (s *shoot) validateUpdate(ctx context.Context, oldShoot, shoot *core.Shoot) allErrors = append(allErrors, validation.ValidateWorkersUpdate(oldValContext.shoot.Spec.Provider.Workers, currentValContext.shoot.Spec.Provider.Workers, workersPath)...) - for i, currentWorkerConfig := range currentValContext.workerConfigs { - for j, oldWorkerConfig := range oldValContext.workerConfigs { + for i, currentContext := range currentValContext.workerConfigsContexts { + currentWorkerConfig := currentContext.workerConfig + for j, oldContext := range oldValContext.workerConfigsContexts { + oldWorkerConfig := oldContext.workerConfig if shoot.Spec.Provider.Workers[i].Name == oldShoot.Spec.Provider.Workers[j].Name && !reflect.DeepEqual(oldWorkerConfig, currentWorkerConfig) { allErrors = append(allErrors, validation.ValidateWorkerConfigUpdate(currentWorkerConfig, oldWorkerConfig, workerConfigPath(i))...) } @@ -191,7 +198,7 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v } } - var workerConfigs []*apiskubevirt.WorkerConfig + var workerConfigsContexts []*workerConfigContext for _, worker := range shoot.Spec.Provider.Workers { workerConfig := &apiskubevirt.WorkerConfig{} if worker.ProviderConfig != nil { @@ -201,7 +208,11 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v return nil, errors.Wrapf(err, "could not decode providerConfig of worker %q", worker.Name) } } - workerConfigs = append(workerConfigs, workerConfig) + + workerConfigsContexts = append(workerConfigsContexts, &workerConfigContext{ + workerConfig: workerConfig, + dataVolumes: worker.DataVolumes, + }) } cloudProfile := &gardencorev1beta1.CloudProfile{} @@ -218,12 +229,12 @@ func (s *shoot) newValidationContext(ctx context.Context, shoot *core.Shoot) (*v } return &validationContext{ - shoot: shoot, - infrastructureConfig: infrastructureConfig, - controlPlaneConfig: controlPlaneConfig, - workerConfigs: workerConfigs, - cloudProfile: cloudProfile, - cloudProfileConfig: cloudProfileConfig, + shoot: shoot, + infrastructureConfig: infrastructureConfig, + controlPlaneConfig: controlPlaneConfig, + workerConfigsContexts: workerConfigsContexts, + cloudProfile: cloudProfile, + cloudProfileConfig: cloudProfileConfig, }, nil } diff --git a/pkg/apis/kubevirt/types_worker.go b/pkg/apis/kubevirt/types_worker.go index 1ded4c44..9f130728 100644 --- a/pkg/apis/kubevirt/types_worker.go +++ b/pkg/apis/kubevirt/types_worker.go @@ -26,8 +26,9 @@ import ( type WorkerConfig struct { metav1.TypeMeta + // Devices allows to customize devices attached to KubeVirt VM + Devices *Devices // CPU allows specifying the CPU topology of KubeVirt VM. - // +optional CPU *kubevirtv1.CPU // Memory allows specifying the VirtualMachineInstance memory features like huge pages and guest memory settings. // Each feature might require appropriate FeatureGate enabled. @@ -54,6 +55,18 @@ type WorkerConfig struct { OvercommitGuestOverhead bool } +// Devices allows to fine-tune devices attached to KubeVirt VM +type Devices struct { + // Disks allows to customize disks attached to KubeVirt VM + Disks []kubevirtv1.Disk + // Whether to have random number generator from host + Rng *kubevirtv1.Rng + // Whether or not to enable virtio multi-queue for block devices + BlockMultiQueue bool + // If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature + NetworkInterfaceMultiQueue bool +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // WorkerStatus contains information about created worker resources. diff --git a/pkg/apis/kubevirt/v1alpha1/types_worker.go b/pkg/apis/kubevirt/v1alpha1/types_worker.go index 50214e58..4f332f52 100644 --- a/pkg/apis/kubevirt/v1alpha1/types_worker.go +++ b/pkg/apis/kubevirt/v1alpha1/types_worker.go @@ -27,6 +27,9 @@ import ( type WorkerConfig struct { metav1.TypeMeta `json:",inline"` + // Devices allows to customize devices attached to KubeVirt VM + // +optional + Devices *Devices `json:"devices,omitempty"` // CPU allows specifying the CPU topology of KubeVirt VM. // +optional CPU *kubevirtv1.CPU `json:"cpu,omitempty"` @@ -60,6 +63,22 @@ type WorkerConfig struct { OvercommitGuestOverhead bool `json:"overcommitGuestOverhead,omitempty"` } +// Devices allows to fine-tune devices attached to KubeVirt VM +type Devices struct { + // Disks allows to customize disks attached to KubeVirt VM + // +optional + Disks []kubevirtv1.Disk `json:"disks,omitempty"` + // Whether to have random number generator from host + // +optional + Rng *kubevirtv1.Rng `json:"rng,omitempty"` + // Whether or not to enable virtio multi-queue for block devices + // +optional + BlockMultiQueue bool `json:"blockMultiQueue,omitempty"` + // If specified, virtual network interfaces configured with a virtio bus will also enable the vhost multiqueue feature + // +optional + NetworkInterfaceMultiQueue bool `json:"networkInterfaceMultiqueue,omitempty"` +} + // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/kubevirt/v1alpha1/zz_generated.conversion.go b/pkg/apis/kubevirt/v1alpha1/zz_generated.conversion.go index 37977ba4..b4d27226 100644 --- a/pkg/apis/kubevirt/v1alpha1/zz_generated.conversion.go +++ b/pkg/apis/kubevirt/v1alpha1/zz_generated.conversion.go @@ -67,6 +67,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*Devices)(nil), (*kubevirt.Devices)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_Devices_To_kubevirt_Devices(a.(*Devices), b.(*kubevirt.Devices), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*kubevirt.Devices)(nil), (*Devices)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kubevirt_Devices_To_v1alpha1_Devices(a.(*kubevirt.Devices), b.(*Devices), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*InfrastructureConfig)(nil), (*kubevirt.InfrastructureConfig)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha1_InfrastructureConfig_To_kubevirt_InfrastructureConfig(a.(*InfrastructureConfig), b.(*kubevirt.InfrastructureConfig), scope) }); err != nil { @@ -262,6 +272,32 @@ func Convert_kubevirt_ControlPlaneConfig_To_v1alpha1_ControlPlaneConfig(in *kube return autoConvert_kubevirt_ControlPlaneConfig_To_v1alpha1_ControlPlaneConfig(in, out, s) } +func autoConvert_v1alpha1_Devices_To_kubevirt_Devices(in *Devices, out *kubevirt.Devices, s conversion.Scope) error { + out.Disks = *(*[]v1.Disk)(unsafe.Pointer(&in.Disks)) + out.Rng = (*v1.Rng)(unsafe.Pointer(in.Rng)) + out.BlockMultiQueue = in.BlockMultiQueue + out.NetworkInterfaceMultiQueue = in.NetworkInterfaceMultiQueue + return nil +} + +// Convert_v1alpha1_Devices_To_kubevirt_Devices is an autogenerated conversion function. +func Convert_v1alpha1_Devices_To_kubevirt_Devices(in *Devices, out *kubevirt.Devices, s conversion.Scope) error { + return autoConvert_v1alpha1_Devices_To_kubevirt_Devices(in, out, s) +} + +func autoConvert_kubevirt_Devices_To_v1alpha1_Devices(in *kubevirt.Devices, out *Devices, s conversion.Scope) error { + out.Disks = *(*[]v1.Disk)(unsafe.Pointer(&in.Disks)) + out.Rng = (*v1.Rng)(unsafe.Pointer(in.Rng)) + out.BlockMultiQueue = in.BlockMultiQueue + out.NetworkInterfaceMultiQueue = in.NetworkInterfaceMultiQueue + return nil +} + +// Convert_kubevirt_Devices_To_v1alpha1_Devices is an autogenerated conversion function. +func Convert_kubevirt_Devices_To_v1alpha1_Devices(in *kubevirt.Devices, out *Devices, s conversion.Scope) error { + return autoConvert_kubevirt_Devices_To_v1alpha1_Devices(in, out, s) +} + func autoConvert_v1alpha1_InfrastructureConfig_To_kubevirt_InfrastructureConfig(in *InfrastructureConfig, out *kubevirt.InfrastructureConfig, s conversion.Scope) error { if err := Convert_v1alpha1_NetworksConfig_To_kubevirt_NetworksConfig(&in.Networks, &out.Networks, s); err != nil { return err @@ -511,6 +547,7 @@ func Convert_kubevirt_TenantNetwork_To_v1alpha1_TenantNetwork(in *kubevirt.Tenan } func autoConvert_v1alpha1_WorkerConfig_To_kubevirt_WorkerConfig(in *WorkerConfig, out *kubevirt.WorkerConfig, s conversion.Scope) error { + out.Devices = (*kubevirt.Devices)(unsafe.Pointer(in.Devices)) out.CPU = (*v1.CPU)(unsafe.Pointer(in.CPU)) out.Memory = (*v1.Memory)(unsafe.Pointer(in.Memory)) out.DNSPolicy = corev1.DNSPolicy(in.DNSPolicy) @@ -526,6 +563,7 @@ func Convert_v1alpha1_WorkerConfig_To_kubevirt_WorkerConfig(in *WorkerConfig, ou } func autoConvert_kubevirt_WorkerConfig_To_v1alpha1_WorkerConfig(in *kubevirt.WorkerConfig, out *WorkerConfig, s conversion.Scope) error { + out.Devices = (*Devices)(unsafe.Pointer(in.Devices)) out.CPU = (*v1.CPU)(unsafe.Pointer(in.CPU)) out.Memory = (*v1.Memory)(unsafe.Pointer(in.Memory)) out.DNSPolicy = corev1.DNSPolicy(in.DNSPolicy) diff --git a/pkg/apis/kubevirt/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/kubevirt/v1alpha1/zz_generated.deepcopy.go index c73dc8db..271fa756 100644 --- a/pkg/apis/kubevirt/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/kubevirt/v1alpha1/zz_generated.deepcopy.go @@ -118,6 +118,34 @@ func (in *ControlPlaneConfig) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Devices) DeepCopyInto(out *Devices) { + *out = *in + if in.Disks != nil { + in, out := &in.Disks, &out.Disks + *out = make([]v1.Disk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Rng != nil { + in, out := &in.Rng, &out.Rng + *out = new(v1.Rng) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Devices. +func (in *Devices) DeepCopy() *Devices { + if in == nil { + return nil + } + out := new(Devices) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InfrastructureConfig) DeepCopyInto(out *InfrastructureConfig) { *out = *in @@ -344,6 +372,11 @@ func (in *TenantNetwork) DeepCopy() *TenantNetwork { func (in *WorkerConfig) DeepCopyInto(out *WorkerConfig) { *out = *in out.TypeMeta = in.TypeMeta + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = new(Devices) + (*in).DeepCopyInto(*out) + } if in.CPU != nil { in, out := &in.CPU, &out.CPU *out = new(v1.CPU) diff --git a/pkg/apis/kubevirt/validation/shoot.go b/pkg/apis/kubevirt/validation/shoot.go index 1e120bcc..f01fb344 100644 --- a/pkg/apis/kubevirt/validation/shoot.go +++ b/pkg/apis/kubevirt/validation/shoot.go @@ -82,6 +82,9 @@ func validateVolume(vol *core.Volume, fldPath *field.Path) field.ErrorList { func validateDataVolume(vol *core.DataVolume, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} + if vol.Name == "" { + allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must not be empty")) + } if vol.Type == nil { allErrs = append(allErrs, field.Required(fldPath.Child("type"), "must not be empty")) } diff --git a/pkg/apis/kubevirt/validation/shoot_test.go b/pkg/apis/kubevirt/validation/shoot_test.go index 42ed6c09..8d2e5680 100644 --- a/pkg/apis/kubevirt/validation/shoot_test.go +++ b/pkg/apis/kubevirt/validation/shoot_test.go @@ -69,6 +69,7 @@ var _ = Describe("Shoot validation", func() { }, DataVolumes: []core.DataVolume{ { + Name: "volume-1", Type: pointer.StringPtr("DataVolume"), VolumeSize: "20G", }, @@ -124,6 +125,19 @@ var _ = Describe("Shoot validation", func() { )) }) + It("should forbid because worker data volume does not have a name", func() { + workers[0].DataVolumes[0].Name = "" + + errorList := ValidateWorkers(workers, nilPath) + + Expect(errorList).To(ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeRequired), + "Field": Equal("[0].dataVolumes[0].name"), + })), + )) + }) + It("should forbid because worker data volume does not have a type", func() { workers[0].DataVolumes[0].Type = nil diff --git a/pkg/apis/kubevirt/validation/worker.go b/pkg/apis/kubevirt/validation/worker.go index 3defb3d3..c3b9aa10 100644 --- a/pkg/apis/kubevirt/validation/worker.go +++ b/pkg/apis/kubevirt/validation/worker.go @@ -19,12 +19,14 @@ import ( apiskubevirt "github.com/gardener/gardener-extension-provider-kubevirt/pkg/apis/kubevirt" - corev1 "k8s.io/api/core/v1" + gardencorev1 "github.com/gardener/gardener/pkg/apis/core" + k8scorev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" ) // ValidateWorkerConfig validates a WorkerConfig object. -func ValidateWorkerConfig(config *apiskubevirt.WorkerConfig, fldPath *field.Path) field.ErrorList { +func ValidateWorkerConfig(config *apiskubevirt.WorkerConfig, dataVolumes []gardencorev1.DataVolume, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if config.DNSPolicy != "" { @@ -32,25 +34,46 @@ func ValidateWorkerConfig(config *apiskubevirt.WorkerConfig, fldPath *field.Path dnsConfigPath := fldPath.Child("dnsConfig") switch config.DNSPolicy { - case corev1.DNSDefault, corev1.DNSClusterFirstWithHostNet, corev1.DNSClusterFirst, corev1.DNSNone: + case k8scorev1.DNSDefault, k8scorev1.DNSClusterFirstWithHostNet, k8scorev1.DNSClusterFirst, k8scorev1.DNSNone: break default: allErrs = append(allErrs, field.Invalid(dnsPolicyPath, config.DNSPolicy, "invalid dns policy")) } - if config.DNSPolicy == corev1.DNSNone { + if config.DNSPolicy == k8scorev1.DNSNone { if config.DNSConfig != nil { if len(config.DNSConfig.Nameservers) == 0 { allErrs = append(allErrs, field.Required(dnsConfigPath.Child("nameservers"), - fmt.Sprintf("cannot be empty when dns policy is %s", corev1.DNSNone))) + fmt.Sprintf("cannot be empty when dns policy is %s", k8scorev1.DNSNone))) } } else { allErrs = append(allErrs, field.Required(dnsConfigPath, - fmt.Sprintf("cannot be empty when dns policy is %s", corev1.DNSNone))) + fmt.Sprintf("cannot be empty when dns policy is %s", k8scorev1.DNSNone))) } } } + if config.Devices != nil { + disksPath := fldPath.Child("devices").Child("disks") + disks := sets.NewString() + + if disksLen := len(config.Devices.Disks); disksLen > len(dataVolumes) { + allErrs = append(allErrs, field.Invalid(disksPath, disksLen, "more defined disks than data volumes")) + } + + for i, disk := range config.Devices.Disks { + if disk.Name == "" { + allErrs = append(allErrs, field.Required(disksPath.Index(i).Child("name"), "cannot be empty")) + } else if disks.Has(disk.Name) { + allErrs = append(allErrs, field.Invalid(disksPath.Index(i).Child("name"), disk.Name, "already exists")) + continue + } else if !hasDiskVolumeMatch(disk.Name, dataVolumes) { + allErrs = append(allErrs, field.Invalid(disksPath.Index(i).Child("name"), disk.Name, "does not have volume pair")) + } + disks.Insert(disk.Name) + } + } + return allErrs } @@ -59,3 +82,12 @@ func ValidateWorkerConfigUpdate(oldConfig, newConfig *apiskubevirt.WorkerConfig, allErrs := field.ErrorList{} return allErrs } + +func hasDiskVolumeMatch(diskName string, volumes []gardencorev1.DataVolume) bool { + for _, volume := range volumes { + if volume.Name == diskName { + return true + } + } + return false +} diff --git a/pkg/apis/kubevirt/validation/worker_test.go b/pkg/apis/kubevirt/validation/worker_test.go index 17c70f86..8525997c 100644 --- a/pkg/apis/kubevirt/validation/worker_test.go +++ b/pkg/apis/kubevirt/validation/worker_test.go @@ -18,13 +18,15 @@ import ( apiskubevirt "github.com/gardener/gardener-extension-provider-kubevirt/pkg/apis/kubevirt" . "github.com/gardener/gardener-extension-provider-kubevirt/pkg/apis/kubevirt/validation" + gardenercorev1 "github.com/gardener/gardener/pkg/apis/core" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gstruct" gomegatypes "github.com/onsi/gomega/types" - corev1 "k8s.io/api/core/v1" + k8scorev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/validation/field" + kubevirtv1 "kubevirt.io/client-go/api/v1" ) var _ = Describe("WorkerConfig validation", func() { @@ -41,39 +43,149 @@ var _ = Describe("WorkerConfig validation", func() { Describe("#ValidateWorkerConfig", func() { DescribeTable("#ValidateDNS", - func(dnsPolicy corev1.DNSPolicy, dnsConfig *corev1.PodDNSConfig, matcher gomegatypes.GomegaMatcher) { + func(dnsPolicy k8scorev1.DNSPolicy, dnsConfig *k8scorev1.PodDNSConfig, matcher gomegatypes.GomegaMatcher) { config.DNSPolicy = dnsPolicy config.DNSConfig = dnsConfig - err := ValidateWorkerConfig(config, nilPath) + err := ValidateWorkerConfig(config, nil, nilPath) Expect(err).To(matcher) }, Entry("should return error when invalid DNS is set", - corev1.DNSPolicy("invalid-policy"), nil, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ + k8scorev1.DNSPolicy("invalid-policy"), nil, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeInvalid), "Field": Equal("dnsPolicy"), }))), ), Entry("should return error when dnsConfig is empty with 'None' dnsPolicy", - corev1.DNSNone, nil, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ + k8scorev1.DNSNone, nil, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeRequired), "Field": Equal("dnsConfig"), }))), ), Entry("should return error when dnsConfig.nameservers is empty with 'None' dnsPolicy", - corev1.DNSNone, &corev1.PodDNSConfig{}, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ + k8scorev1.DNSNone, &k8scorev1.PodDNSConfig{}, ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ "Type": Equal(field.ErrorTypeRequired), "Field": Equal("dnsConfig.nameservers"), }))), ), Entry("should not return error when dnsConfig.nameservers is set with 'None' dnsPolicy", - corev1.DNSNone, &corev1.PodDNSConfig{Nameservers: []string{"8.8.8.8"}}, Equal(field.ErrorList{}), + k8scorev1.DNSNone, &k8scorev1.PodDNSConfig{Nameservers: []string{"8.8.8.8"}}, Equal(field.ErrorList{}), ), Entry("should not return error with appropriate dnsPolicy", - corev1.DNSDefault, nil, Equal(field.ErrorList{}), + k8scorev1.DNSDefault, nil, Equal(field.ErrorList{}), ), Entry("should not return error with appropriate dnsPolicy and dnsConfig", - corev1.DNSDefault, &corev1.PodDNSConfig{Nameservers: []string{"8.8.8.8"}}, Equal(field.ErrorList{}), + k8scorev1.DNSDefault, &k8scorev1.PodDNSConfig{Nameservers: []string{"8.8.8.8"}}, Equal(field.ErrorList{}), + ), + ) + + DescribeTable("#ValidateDisksAndVolumes", + func(disks []kubevirtv1.Disk, dataVolumes []gardenercorev1.DataVolume, matcher gomegatypes.GomegaMatcher) { + config.Devices = &apiskubevirt.Devices{ + Disks: disks, + } + err := ValidateWorkerConfig(config, dataVolumes, nilPath) + Expect(err).To(matcher) + }, + Entry("should not return error with appropriate disks and volumes match", + []kubevirtv1.Disk{ + { + Name: "disk-1", + }, + { + Name: "disk-2", + }, + }, + []gardenercorev1.DataVolume{ + { + Name: "disk-1", + }, + { + Name: "disk-2", + }, + }, + Equal(field.ErrorList{}), + ), + Entry("should return error with empty disk name", + []kubevirtv1.Disk{ + { + Name: "", + }, + }, + []gardenercorev1.DataVolume{ + { + Name: "disk-1", + }, + }, + ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeRequired), + "Field": Equal("devices.disks[0].name"), + }))), + ), + Entry("should return error with disks and volumes that do not match", + []kubevirtv1.Disk{ + { + Name: "disk-1a", + }, + }, + []gardenercorev1.DataVolume{ + { + Name: "disk-1b", + }, + }, + ConsistOf(PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("devices.disks[0].name"), + }))), + ), + Entry("should return error with number of disks bigger than volumes", + []kubevirtv1.Disk{ + { + Name: "disk-1", + }, + { + Name: "disk-2", + }, + }, + []gardenercorev1.DataVolume{ + { + Name: "disk-1", + }, + }, + ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("devices.disks"), + })), + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("devices.disks[1].name"), + })), + ), + ), + Entry("should return error with duplicated disks names", + []kubevirtv1.Disk{ + { + Name: "disk-1", + }, + { + Name: "disk-1", + }, + }, + []gardenercorev1.DataVolume{ + { + Name: "disk-1", + }, + { + Name: "disk-2", + }, + }, + ConsistOf( + PointTo(MatchFields(IgnoreExtras, Fields{ + "Type": Equal(field.ErrorTypeInvalid), + "Field": Equal("devices.disks[1].name"), + })), + ), ), ) diff --git a/pkg/apis/kubevirt/zz_generated.deepcopy.go b/pkg/apis/kubevirt/zz_generated.deepcopy.go index ac6990f9..2b36fb13 100644 --- a/pkg/apis/kubevirt/zz_generated.deepcopy.go +++ b/pkg/apis/kubevirt/zz_generated.deepcopy.go @@ -118,6 +118,34 @@ func (in *ControlPlaneConfig) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Devices) DeepCopyInto(out *Devices) { + *out = *in + if in.Disks != nil { + in, out := &in.Disks, &out.Disks + *out = make([]v1.Disk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Rng != nil { + in, out := &in.Rng, &out.Rng + *out = new(v1.Rng) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Devices. +func (in *Devices) DeepCopy() *Devices { + if in == nil { + return nil + } + out := new(Devices) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InfrastructureConfig) DeepCopyInto(out *InfrastructureConfig) { *out = *in @@ -344,6 +372,11 @@ func (in *TenantNetwork) DeepCopy() *TenantNetwork { func (in *WorkerConfig) DeepCopyInto(out *WorkerConfig) { *out = *in out.TypeMeta = in.TypeMeta + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = new(Devices) + (*in).DeepCopyInto(*out) + } if in.CPU != nil { in, out := &in.CPU, &out.CPU *out = new(v1.CPU) diff --git a/pkg/controller/worker/machines.go b/pkg/controller/worker/machines.go index 3a8d69fc..0c56c369 100644 --- a/pkg/controller/worker/machines.go +++ b/pkg/controller/worker/machines.go @@ -188,12 +188,13 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { // Build additional volumes var additionalVolumes []map[string]interface{} for _, volume := range pool.DataVolumes { - className, size, err := w.getStorageClassNameAndSize(*volume.Type, volume.Size) + storageClassName, size, err := w.getStorageClassNameAndSize(*volume.Type, volume.Size) if err != nil { return err } additionalVolumes = append(additionalVolumes, map[string]interface{}{ - "dataVolume": buildDataVolumeSpecWithBlankSource(className, size), + "name": volume.Name, + "dataVolume": buildDataVolumeSpecWithBlankSource(storageClassName, size), }) } @@ -217,6 +218,7 @@ func (w *workerDelegate) generateMachineConfig(ctx context.Context) error { "region": w.worker.Spec.Region, "zone": zone, "resources": resourceRequirements, + "devices": workerConfig.Devices, "rootVolume": rootVolume, "additionalVolumes": additionalVolumes, "sshKeys": []string{string(w.worker.Spec.SSHPublicKey)}, diff --git a/pkg/controller/worker/machines_test.go b/pkg/controller/worker/machines_test.go index 474aa090..fdd0d646 100644 --- a/pkg/controller/worker/machines_test.go +++ b/pkg/controller/worker/machines_test.go @@ -124,6 +124,8 @@ var _ = Describe("Machines", func() { networkName := "default/net-conf" networkSHA := "abc" dnsNameserver := "8.8.8.8" + rootDiskName := "root-disk" + additionalDV1 := "dv1" images := []kubevirtv1alpha1.MachineImages{ { @@ -182,6 +184,19 @@ var _ = Describe("Machines", func() { APIVersion: "kubevirt.provider.extensions.gardener.cloud/v1alpha1", Kind: "WorkerConfig", }, + Devices: &kubevirtv1alpha1.Devices{ + Disks: []kubevirtv1.Disk{ + { + Name: rootDiskName, + DiskDevice: kubevirtv1.DiskDevice{ + Disk: &kubevirtv1.DiskTarget{ + Bus: "virtio", + }, + }, + Cache: kubevirtv1.CacheNone, + }, + }, + }, CPU: &kubevirtv1.CPU{ Cores: uint32(1), Sockets: uint32(2), @@ -219,12 +234,35 @@ var _ = Describe("Machines", func() { }, DataVolumes: []extensionsv1alpha1.DataVolume{ { + Name: additionalDV1, Type: pointer.StringPtr("standard"), Size: "10Gi", }, }, UserData: userData, Zones: []string{"local-3"}, + ProviderConfig: &runtime.RawExtension{ + Raw: encode(&kubevirtv1alpha1.WorkerConfig{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "kubevirt.provider.extensions.gardener.cloud/v1alpha1", + Kind: "WorkerConfig", + }, + Devices: &kubevirtv1alpha1.Devices{ + Disks: []kubevirtv1.Disk{ + { + Name: additionalDV1, + DiskDevice: kubevirtv1.DiskDevice{ + Disk: &kubevirtv1.DiskTarget{ + Bus: "virtio", + }, + }, + Cache: kubevirtv1.CacheNone, + }, + }, + NetworkInterfaceMultiQueue: true, + }, + }), + }, }, }, SSHPublicKey: sshPublicKey, @@ -288,6 +326,19 @@ var _ = Describe("Machines", func() { }, OvercommitGuestOverhead: true, }, + &apiskubevirt.Devices{ + Disks: []kubevirtv1.Disk{ + { + Name: rootDiskName, + DiskDevice: kubevirtv1.DiskDevice{ + Disk: &kubevirtv1.DiskTarget{ + Bus: "virtio", + }, + }, + Cache: kubevirtv1.CacheNone, + }, + }, + }, &cdicorev1alpha1.DataVolumeSpec{ PVC: &corev1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{ @@ -344,6 +395,19 @@ var _ = Describe("Machines", func() { }, OvercommitGuestOverhead: true, }, + &apiskubevirt.Devices{ + Disks: []kubevirtv1.Disk{ + { + Name: rootDiskName, + DiskDevice: kubevirtv1.DiskDevice{ + Disk: &kubevirtv1.DiskTarget{ + Bus: "virtio", + }, + }, + Cache: kubevirtv1.CacheNone, + }, + }, + }, &cdicorev1alpha1.DataVolumeSpec{ PVC: &corev1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{ @@ -395,6 +459,20 @@ var _ = Describe("Machines", func() { corev1.ResourceMemory: resource.MustParse("8192Mi"), }, }, + &apiskubevirt.Devices{ + Disks: []kubevirtv1.Disk{ + { + Name: additionalDV1, + DiskDevice: kubevirtv1.DiskDevice{ + Disk: &kubevirtv1.DiskTarget{ + Bus: "virtio", + }, + }, + Cache: kubevirtv1.CacheNone, + }, + }, + NetworkInterfaceMultiQueue: true, + }, &cdicorev1alpha1.DataVolumeSpec{ PVC: &corev1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{ @@ -416,6 +494,7 @@ var _ = Describe("Machines", func() { }, []map[string]interface{}{ { + "name": additionalDV1, "dataVolume": &cdicorev1alpha1.DataVolumeSpec{ PVC: &corev1.PersistentVolumeClaimSpec{ AccessModes: []corev1.PersistentVolumeAccessMode{ @@ -651,6 +730,7 @@ func createMachineClass( classTemplate map[string]interface{}, name, zone string, resources *kubevirtv1.ResourceRequirements, + devices *apiskubevirt.Devices, rootVolume *cdicorev1alpha1.DataVolumeSpec, additionalVolumes []map[string]interface{}, cpu *kubevirtv1.CPU, @@ -667,6 +747,7 @@ func createMachineClass( out["name"] = name out["zone"] = zone out["resources"] = resources + out["devices"] = devices out["rootVolume"] = rootVolume out["additionalVolumes"] = additionalVolumes out["cpu"] = cpu diff --git a/pkg/mock/client/mocks.go b/pkg/mock/client/mocks.go index 236dad12..9abee9c3 100644 --- a/pkg/mock/client/mocks.go +++ b/pkg/mock/client/mocks.go @@ -6,38 +6,37 @@ package client import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" runtime "k8s.io/apimachinery/pkg/runtime" types "k8s.io/apimachinery/pkg/types" + reflect "reflect" client "sigs.k8s.io/controller-runtime/pkg/client" ) -// MockClient is a mock of Client interface. +// MockClient is a mock of Client interface type MockClient struct { ctrl *gomock.Controller recorder *MockClientMockRecorder } -// MockClientMockRecorder is the mock recorder for MockClient. +// MockClientMockRecorder is the mock recorder for MockClient type MockClientMockRecorder struct { mock *MockClient } -// NewMockClient creates a new mock instance. +// NewMockClient creates a new mock instance func NewMockClient(ctrl *gomock.Controller) *MockClient { mock := &MockClient{ctrl: ctrl} mock.recorder = &MockClientMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockClient) EXPECT() *MockClientMockRecorder { return m.recorder } -// Create mocks base method. +// Create mocks base method func (m *MockClient) Create(arg0 context.Context, arg1 runtime.Object, arg2 ...client.CreateOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -49,14 +48,14 @@ func (m *MockClient) Create(arg0 context.Context, arg1 runtime.Object, arg2 ...c return ret0 } -// Create indicates an expected call of Create. +// Create indicates an expected call of Create func (mr *MockClientMockRecorder) Create(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockClient)(nil).Create), varargs...) } -// Delete mocks base method. +// Delete mocks base method func (m *MockClient) Delete(arg0 context.Context, arg1 runtime.Object, arg2 ...client.DeleteOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -68,14 +67,14 @@ func (m *MockClient) Delete(arg0 context.Context, arg1 runtime.Object, arg2 ...c return ret0 } -// Delete indicates an expected call of Delete. +// Delete indicates an expected call of Delete func (mr *MockClientMockRecorder) Delete(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockClient)(nil).Delete), varargs...) } -// DeleteAllOf mocks base method. +// DeleteAllOf mocks base method func (m *MockClient) DeleteAllOf(arg0 context.Context, arg1 runtime.Object, arg2 ...client.DeleteAllOfOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -87,14 +86,14 @@ func (m *MockClient) DeleteAllOf(arg0 context.Context, arg1 runtime.Object, arg2 return ret0 } -// DeleteAllOf indicates an expected call of DeleteAllOf. +// DeleteAllOf indicates an expected call of DeleteAllOf func (mr *MockClientMockRecorder) DeleteAllOf(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAllOf", reflect.TypeOf((*MockClient)(nil).DeleteAllOf), varargs...) } -// Get mocks base method. +// Get mocks base method func (m *MockClient) Get(arg0 context.Context, arg1 types.NamespacedName, arg2 runtime.Object) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", arg0, arg1, arg2) @@ -102,13 +101,13 @@ func (m *MockClient) Get(arg0 context.Context, arg1 types.NamespacedName, arg2 r return ret0 } -// Get indicates an expected call of Get. +// Get indicates an expected call of Get func (mr *MockClientMockRecorder) Get(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockClient)(nil).Get), arg0, arg1, arg2) } -// List mocks base method. +// List mocks base method func (m *MockClient) List(arg0 context.Context, arg1 runtime.Object, arg2 ...client.ListOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -120,14 +119,14 @@ func (m *MockClient) List(arg0 context.Context, arg1 runtime.Object, arg2 ...cli return ret0 } -// List indicates an expected call of List. +// List indicates an expected call of List func (mr *MockClientMockRecorder) List(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockClient)(nil).List), varargs...) } -// Patch mocks base method. +// Patch mocks base method func (m *MockClient) Patch(arg0 context.Context, arg1 runtime.Object, arg2 client.Patch, arg3 ...client.PatchOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1, arg2} @@ -139,14 +138,14 @@ func (m *MockClient) Patch(arg0 context.Context, arg1 runtime.Object, arg2 clien return ret0 } -// Patch indicates an expected call of Patch. +// Patch indicates an expected call of Patch func (mr *MockClientMockRecorder) Patch(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Patch", reflect.TypeOf((*MockClient)(nil).Patch), varargs...) } -// Status mocks base method. +// Status mocks base method func (m *MockClient) Status() client.StatusWriter { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Status") @@ -154,13 +153,13 @@ func (m *MockClient) Status() client.StatusWriter { return ret0 } -// Status indicates an expected call of Status. +// Status indicates an expected call of Status func (mr *MockClientMockRecorder) Status() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockClient)(nil).Status)) } -// Update mocks base method. +// Update mocks base method func (m *MockClient) Update(arg0 context.Context, arg1 runtime.Object, arg2 ...client.UpdateOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -172,37 +171,37 @@ func (m *MockClient) Update(arg0 context.Context, arg1 runtime.Object, arg2 ...c return ret0 } -// Update indicates an expected call of Update. +// Update indicates an expected call of Update func (mr *MockClientMockRecorder) Update(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockClient)(nil).Update), varargs...) } -// MockStatusWriter is a mock of StatusWriter interface. +// MockStatusWriter is a mock of StatusWriter interface type MockStatusWriter struct { ctrl *gomock.Controller recorder *MockStatusWriterMockRecorder } -// MockStatusWriterMockRecorder is the mock recorder for MockStatusWriter. +// MockStatusWriterMockRecorder is the mock recorder for MockStatusWriter type MockStatusWriterMockRecorder struct { mock *MockStatusWriter } -// NewMockStatusWriter creates a new mock instance. +// NewMockStatusWriter creates a new mock instance func NewMockStatusWriter(ctrl *gomock.Controller) *MockStatusWriter { mock := &MockStatusWriter{ctrl: ctrl} mock.recorder = &MockStatusWriterMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockStatusWriter) EXPECT() *MockStatusWriterMockRecorder { return m.recorder } -// Patch mocks base method. +// Patch mocks base method func (m *MockStatusWriter) Patch(arg0 context.Context, arg1 runtime.Object, arg2 client.Patch, arg3 ...client.PatchOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1, arg2} @@ -214,14 +213,14 @@ func (m *MockStatusWriter) Patch(arg0 context.Context, arg1 runtime.Object, arg2 return ret0 } -// Patch indicates an expected call of Patch. +// Patch indicates an expected call of Patch func (mr *MockStatusWriterMockRecorder) Patch(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Patch", reflect.TypeOf((*MockStatusWriter)(nil).Patch), varargs...) } -// Update mocks base method. +// Update mocks base method func (m *MockStatusWriter) Update(arg0 context.Context, arg1 runtime.Object, arg2 ...client.UpdateOption) error { m.ctrl.T.Helper() varargs := []interface{}{arg0, arg1} @@ -233,7 +232,7 @@ func (m *MockStatusWriter) Update(arg0 context.Context, arg1 runtime.Object, arg return ret0 } -// Update indicates an expected call of Update. +// Update indicates an expected call of Update func (mr *MockStatusWriterMockRecorder) Update(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() varargs := append([]interface{}{arg0, arg1}, arg2...) diff --git a/pkg/mock/kubevirt/mocks.go b/pkg/mock/kubevirt/mocks.go index f5780725..945e7724 100644 --- a/pkg/mock/kubevirt/mocks.go +++ b/pkg/mock/kubevirt/mocks.go @@ -6,38 +6,37 @@ package kubevirt import ( context "context" - reflect "reflect" - gomock "github.com/golang/mock/gomock" v1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" v1alpha1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1" + reflect "reflect" client "sigs.k8s.io/controller-runtime/pkg/client" ) -// MockClientFactory is a mock of ClientFactory interface. +// MockClientFactory is a mock of ClientFactory interface type MockClientFactory struct { ctrl *gomock.Controller recorder *MockClientFactoryMockRecorder } -// MockClientFactoryMockRecorder is the mock recorder for MockClientFactory. +// MockClientFactoryMockRecorder is the mock recorder for MockClientFactory type MockClientFactoryMockRecorder struct { mock *MockClientFactory } -// NewMockClientFactory creates a new mock instance. +// NewMockClientFactory creates a new mock instance func NewMockClientFactory(ctrl *gomock.Controller) *MockClientFactory { mock := &MockClientFactory{ctrl: ctrl} mock.recorder = &MockClientFactoryMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockClientFactory) EXPECT() *MockClientFactoryMockRecorder { return m.recorder } -// GetClient mocks base method. +// GetClient mocks base method func (m *MockClientFactory) GetClient(arg0 []byte) (client.Client, string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetClient", arg0) @@ -47,36 +46,36 @@ func (m *MockClientFactory) GetClient(arg0 []byte) (client.Client, string, error return ret0, ret1, ret2 } -// GetClient indicates an expected call of GetClient. +// GetClient indicates an expected call of GetClient func (mr *MockClientFactoryMockRecorder) GetClient(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClient", reflect.TypeOf((*MockClientFactory)(nil).GetClient), arg0) } -// MockDataVolumeManager is a mock of DataVolumeManager interface. +// MockDataVolumeManager is a mock of DataVolumeManager interface type MockDataVolumeManager struct { ctrl *gomock.Controller recorder *MockDataVolumeManagerMockRecorder } -// MockDataVolumeManagerMockRecorder is the mock recorder for MockDataVolumeManager. +// MockDataVolumeManagerMockRecorder is the mock recorder for MockDataVolumeManager type MockDataVolumeManagerMockRecorder struct { mock *MockDataVolumeManager } -// NewMockDataVolumeManager creates a new mock instance. +// NewMockDataVolumeManager creates a new mock instance func NewMockDataVolumeManager(ctrl *gomock.Controller) *MockDataVolumeManager { mock := &MockDataVolumeManager{ctrl: ctrl} mock.recorder = &MockDataVolumeManagerMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockDataVolumeManager) EXPECT() *MockDataVolumeManagerMockRecorder { return m.recorder } -// CreateOrUpdateDataVolume mocks base method. +// CreateOrUpdateDataVolume mocks base method func (m *MockDataVolumeManager) CreateOrUpdateDataVolume(arg0 context.Context, arg1 []byte, arg2 string, arg3 map[string]string, arg4 v1alpha1.DataVolumeSpec) (*v1alpha1.DataVolume, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateOrUpdateDataVolume", arg0, arg1, arg2, arg3, arg4) @@ -85,13 +84,13 @@ func (m *MockDataVolumeManager) CreateOrUpdateDataVolume(arg0 context.Context, a return ret0, ret1 } -// CreateOrUpdateDataVolume indicates an expected call of CreateOrUpdateDataVolume. +// CreateOrUpdateDataVolume indicates an expected call of CreateOrUpdateDataVolume func (mr *MockDataVolumeManagerMockRecorder) CreateOrUpdateDataVolume(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateDataVolume", reflect.TypeOf((*MockDataVolumeManager)(nil).CreateOrUpdateDataVolume), arg0, arg1, arg2, arg3, arg4) } -// DeleteDataVolume mocks base method. +// DeleteDataVolume mocks base method func (m *MockDataVolumeManager) DeleteDataVolume(arg0 context.Context, arg1 []byte, arg2 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteDataVolume", arg0, arg1, arg2) @@ -99,13 +98,13 @@ func (m *MockDataVolumeManager) DeleteDataVolume(arg0 context.Context, arg1 []by return ret0 } -// DeleteDataVolume indicates an expected call of DeleteDataVolume. +// DeleteDataVolume indicates an expected call of DeleteDataVolume func (mr *MockDataVolumeManagerMockRecorder) DeleteDataVolume(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDataVolume", reflect.TypeOf((*MockDataVolumeManager)(nil).DeleteDataVolume), arg0, arg1, arg2) } -// ListDataVolumes mocks base method. +// ListDataVolumes mocks base method func (m *MockDataVolumeManager) ListDataVolumes(arg0 context.Context, arg1 []byte, arg2 map[string]string) (*v1alpha1.DataVolumeList, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListDataVolumes", arg0, arg1, arg2) @@ -114,36 +113,36 @@ func (m *MockDataVolumeManager) ListDataVolumes(arg0 context.Context, arg1 []byt return ret0, ret1 } -// ListDataVolumes indicates an expected call of ListDataVolumes. +// ListDataVolumes indicates an expected call of ListDataVolumes func (mr *MockDataVolumeManagerMockRecorder) ListDataVolumes(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListDataVolumes", reflect.TypeOf((*MockDataVolumeManager)(nil).ListDataVolumes), arg0, arg1, arg2) } -// MockNetworkManager is a mock of NetworkManager interface. +// MockNetworkManager is a mock of NetworkManager interface type MockNetworkManager struct { ctrl *gomock.Controller recorder *MockNetworkManagerMockRecorder } -// MockNetworkManagerMockRecorder is the mock recorder for MockNetworkManager. +// MockNetworkManagerMockRecorder is the mock recorder for MockNetworkManager type MockNetworkManagerMockRecorder struct { mock *MockNetworkManager } -// NewMockNetworkManager creates a new mock instance. +// NewMockNetworkManager creates a new mock instance func NewMockNetworkManager(ctrl *gomock.Controller) *MockNetworkManager { mock := &MockNetworkManager{ctrl: ctrl} mock.recorder = &MockNetworkManagerMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockNetworkManager) EXPECT() *MockNetworkManagerMockRecorder { return m.recorder } -// CreateOrUpdateNetworkAttachmentDefinition mocks base method. +// CreateOrUpdateNetworkAttachmentDefinition mocks base method func (m *MockNetworkManager) CreateOrUpdateNetworkAttachmentDefinition(arg0 context.Context, arg1 []byte, arg2 string, arg3 map[string]string, arg4 string) (*v1.NetworkAttachmentDefinition, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateOrUpdateNetworkAttachmentDefinition", arg0, arg1, arg2, arg3, arg4) @@ -152,13 +151,13 @@ func (m *MockNetworkManager) CreateOrUpdateNetworkAttachmentDefinition(arg0 cont return ret0, ret1 } -// CreateOrUpdateNetworkAttachmentDefinition indicates an expected call of CreateOrUpdateNetworkAttachmentDefinition. +// CreateOrUpdateNetworkAttachmentDefinition indicates an expected call of CreateOrUpdateNetworkAttachmentDefinition func (mr *MockNetworkManagerMockRecorder) CreateOrUpdateNetworkAttachmentDefinition(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateNetworkAttachmentDefinition", reflect.TypeOf((*MockNetworkManager)(nil).CreateOrUpdateNetworkAttachmentDefinition), arg0, arg1, arg2, arg3, arg4) } -// DeleteNetworkAttachmentDefinition mocks base method. +// DeleteNetworkAttachmentDefinition mocks base method func (m *MockNetworkManager) DeleteNetworkAttachmentDefinition(arg0 context.Context, arg1 []byte, arg2 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeleteNetworkAttachmentDefinition", arg0, arg1, arg2) @@ -166,13 +165,13 @@ func (m *MockNetworkManager) DeleteNetworkAttachmentDefinition(arg0 context.Cont return ret0 } -// DeleteNetworkAttachmentDefinition indicates an expected call of DeleteNetworkAttachmentDefinition. +// DeleteNetworkAttachmentDefinition indicates an expected call of DeleteNetworkAttachmentDefinition func (mr *MockNetworkManagerMockRecorder) DeleteNetworkAttachmentDefinition(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNetworkAttachmentDefinition", reflect.TypeOf((*MockNetworkManager)(nil).DeleteNetworkAttachmentDefinition), arg0, arg1, arg2) } -// GetNetworkAttachmentDefinition mocks base method. +// GetNetworkAttachmentDefinition mocks base method func (m *MockNetworkManager) GetNetworkAttachmentDefinition(arg0 context.Context, arg1 []byte, arg2, arg3 string) (*v1.NetworkAttachmentDefinition, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetNetworkAttachmentDefinition", arg0, arg1, arg2, arg3) @@ -181,13 +180,13 @@ func (m *MockNetworkManager) GetNetworkAttachmentDefinition(arg0 context.Context return ret0, ret1 } -// GetNetworkAttachmentDefinition indicates an expected call of GetNetworkAttachmentDefinition. +// GetNetworkAttachmentDefinition indicates an expected call of GetNetworkAttachmentDefinition func (mr *MockNetworkManagerMockRecorder) GetNetworkAttachmentDefinition(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkAttachmentDefinition", reflect.TypeOf((*MockNetworkManager)(nil).GetNetworkAttachmentDefinition), arg0, arg1, arg2, arg3) } -// ListNetworkAttachmentDefinitions mocks base method. +// ListNetworkAttachmentDefinitions mocks base method func (m *MockNetworkManager) ListNetworkAttachmentDefinitions(arg0 context.Context, arg1 []byte, arg2 map[string]string) (*v1.NetworkAttachmentDefinitionList, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListNetworkAttachmentDefinitions", arg0, arg1, arg2) @@ -196,7 +195,7 @@ func (m *MockNetworkManager) ListNetworkAttachmentDefinitions(arg0 context.Conte return ret0, ret1 } -// ListNetworkAttachmentDefinitions indicates an expected call of ListNetworkAttachmentDefinitions. +// ListNetworkAttachmentDefinitions indicates an expected call of ListNetworkAttachmentDefinitions func (mr *MockNetworkManagerMockRecorder) ListNetworkAttachmentDefinitions(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListNetworkAttachmentDefinitions", reflect.TypeOf((*MockNetworkManager)(nil).ListNetworkAttachmentDefinitions), arg0, arg1, arg2) diff --git a/pkg/mock/worker/mocks.go b/pkg/mock/worker/mocks.go index 35c766de..e883401c 100644 --- a/pkg/mock/worker/mocks.go +++ b/pkg/mock/worker/mocks.go @@ -6,37 +6,36 @@ package worker import ( context "context" - reflect "reflect" - v1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" extensions "github.com/gardener/gardener/pkg/extensions" gomock "github.com/golang/mock/gomock" + reflect "reflect" ) -// MockActuator is a mock of Actuator interface. +// MockActuator is a mock of Actuator interface type MockActuator struct { ctrl *gomock.Controller recorder *MockActuatorMockRecorder } -// MockActuatorMockRecorder is the mock recorder for MockActuator. +// MockActuatorMockRecorder is the mock recorder for MockActuator type MockActuatorMockRecorder struct { mock *MockActuator } -// NewMockActuator creates a new mock instance. +// NewMockActuator creates a new mock instance func NewMockActuator(ctrl *gomock.Controller) *MockActuator { mock := &MockActuator{ctrl: ctrl} mock.recorder = &MockActuatorMockRecorder{mock} return mock } -// EXPECT returns an object that allows the caller to indicate expected use. +// EXPECT returns an object that allows the caller to indicate expected use func (m *MockActuator) EXPECT() *MockActuatorMockRecorder { return m.recorder } -// Delete mocks base method. +// Delete mocks base method func (m *MockActuator) Delete(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 *extensions.Cluster) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Delete", arg0, arg1, arg2) @@ -44,13 +43,13 @@ func (m *MockActuator) Delete(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 return ret0 } -// Delete indicates an expected call of Delete. +// Delete indicates an expected call of Delete func (mr *MockActuatorMockRecorder) Delete(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockActuator)(nil).Delete), arg0, arg1, arg2) } -// Migrate mocks base method. +// Migrate mocks base method func (m *MockActuator) Migrate(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 *extensions.Cluster) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Migrate", arg0, arg1, arg2) @@ -58,13 +57,13 @@ func (m *MockActuator) Migrate(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 return ret0 } -// Migrate indicates an expected call of Migrate. +// Migrate indicates an expected call of Migrate func (mr *MockActuatorMockRecorder) Migrate(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Migrate", reflect.TypeOf((*MockActuator)(nil).Migrate), arg0, arg1, arg2) } -// Reconcile mocks base method. +// Reconcile mocks base method func (m *MockActuator) Reconcile(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 *extensions.Cluster) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Reconcile", arg0, arg1, arg2) @@ -72,13 +71,13 @@ func (m *MockActuator) Reconcile(arg0 context.Context, arg1 *v1alpha1.Worker, ar return ret0 } -// Reconcile indicates an expected call of Reconcile. +// Reconcile indicates an expected call of Reconcile func (mr *MockActuatorMockRecorder) Reconcile(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reconcile", reflect.TypeOf((*MockActuator)(nil).Reconcile), arg0, arg1, arg2) } -// Restore mocks base method. +// Restore mocks base method func (m *MockActuator) Restore(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 *extensions.Cluster) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Restore", arg0, arg1, arg2) @@ -86,7 +85,7 @@ func (m *MockActuator) Restore(arg0 context.Context, arg1 *v1alpha1.Worker, arg2 return ret0 } -// Restore indicates an expected call of Restore. +// Restore indicates an expected call of Restore func (mr *MockActuatorMockRecorder) Restore(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Restore", reflect.TypeOf((*MockActuator)(nil).Restore), arg0, arg1, arg2)