mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00
Enable WebhookPvcRendering feature gate by default (#3736)
The feature is available since v1.59, and we enable it by default to allow increasing PVC size to the minimum supported by its provisioner (#3711), and mainly in order to support: https://github.com/kubevirt/kubevirt/pull/14637 As a bonus, the related Serial tests are now parallel. Thanks akalenyu:) Signed-off-by: Arnon Gilboa <agilboa@redhat.com>
This commit is contained in:
parent
5db5951581
commit
0b3f786ee6
@ -10,7 +10,7 @@ CDI volume populators already cover almost all DV import/clone/upload functional
|
||||
|
||||
## Configuration
|
||||
|
||||
To be fully compatible with any external tools that may already use CDI, this new feature has to be enabled by the feature gate: `WebhookPvcRendering`. In the released `cdi-cr` it is disabled by default. To enable it, add the feature gate in the `CDI` custom resource, under spec.config (see [cdi-config doc](./cdi-config.md)).
|
||||
To be fully compatible with any external tools that may already use CDI, this feature has to be enabled by the feature gate: `WebhookPvcRendering`. In the released `cdi-cr` it is enabled by default. To disable it, remove the feature gate from the `CDI` custom resource spec.config (see [cdi-config doc](./cdi-config.md)).
|
||||
|
||||
A Snippet below shows CDI resource with `WebhookPvcRendering` enabled.
|
||||
```yaml
|
||||
|
@ -6,6 +6,7 @@ spec:
|
||||
config:
|
||||
featureGates:
|
||||
- HonorWaitForFirstConsumer
|
||||
- WebhookPvcRendering
|
||||
imagePullPolicy: {{.PullPolicy}}
|
||||
infra:
|
||||
nodeSelector:
|
||||
|
@ -83,7 +83,6 @@ go_test(
|
||||
"//vendor/github.com/openshift/client-go/security/clientset/versioned:go_default_library",
|
||||
"//vendor/github.com/openshift/custom-resource-status/conditions/v1:go_default_library",
|
||||
"//vendor/github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/admissionregistration/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/authorization/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"kubevirt.io/containerized-data-importer/pkg/common"
|
||||
"kubevirt.io/containerized-data-importer/pkg/controller/clone"
|
||||
cc "kubevirt.io/containerized-data-importer/pkg/controller/common"
|
||||
"kubevirt.io/containerized-data-importer/tests"
|
||||
"kubevirt.io/containerized-data-importer/tests/framework"
|
||||
"kubevirt.io/containerized-data-importer/tests/utils"
|
||||
)
|
||||
@ -52,10 +51,6 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
}
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
tests.DisableWebhookPvcRendering(f.CrClient)
|
||||
})
|
||||
|
||||
createSource := func(sz resource.Quantity, vm corev1.PersistentVolumeMode) *corev1.PersistentVolumeClaim {
|
||||
dataVolume := utils.NewDataVolumeWithHTTPImport(sourceName, sz.String(), fmt.Sprintf(utils.TinyCoreIsoURL, f.CdiInstallNs))
|
||||
dataVolume.Spec.PVC.VolumeMode = &vm
|
||||
@ -188,7 +183,6 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
|
||||
// Create target PVC without AccessModes and Resources.Requests, both to be auto-completed by the webhook rendering
|
||||
createIncompleteTarget := func(sz *resource.Quantity, vm corev1.PersistentVolumeMode, strategy, scName string) *corev1.PersistentVolumeClaim {
|
||||
tests.EnableWebhookPvcRendering(f.CrClient)
|
||||
size := resource.Quantity{}
|
||||
if sz != nil {
|
||||
size = *sz
|
||||
@ -251,7 +245,7 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
Expect(targetHash).To(Equal(sourceHash))
|
||||
},
|
||||
Entry("[test_id:10973]with immediateBinding annotation", false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10974]with incomplete target PVC webhook rendering", Serial, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10974]with incomplete target PVC webhook rendering", true),
|
||||
)
|
||||
|
||||
It("should do filesystem to filesystem clone, source created after target", func() {
|
||||
@ -304,7 +298,7 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
f.ExpectCloneFallback(target, clone.IncompatibleVolumeModes, clone.MessageIncompatibleVolumeModes)
|
||||
},
|
||||
Entry("[test_id:10975]with valid target PVC", false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10976]with incomplete target PVC webhook rendering", Serial, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10976]with incomplete target PVC webhook rendering", true),
|
||||
)
|
||||
|
||||
DescribeTable("should do filesystem to block clone", func(webhookRendering bool) {
|
||||
@ -327,7 +321,7 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
f.ExpectCloneFallback(target, clone.IncompatibleVolumeModes, clone.MessageIncompatibleVolumeModes)
|
||||
},
|
||||
Entry("[test_id:11044]with valid target PVC", false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11013]with incomplete target PVC webhook rendering", Serial, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11013]with incomplete target PVC webhook rendering", true),
|
||||
)
|
||||
|
||||
DescribeTable("should clone explicit types requested by user", func(cloneType string, webhookRendering bool, canDo func() bool) {
|
||||
@ -348,11 +342,11 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
Expect(targetHash).To(Equal(sourceHash))
|
||||
},
|
||||
Entry("[test_id:10977]should do csi clone if possible", "csi-clone", false, f.IsCSIVolumeCloneStorageClassAvailable),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10992]should do csi clone if possible, with pvc webhook rendering", Serial, "csi-clone", true, f.IsCSIVolumeCloneStorageClassAvailable),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10992]should do csi clone if possible, with pvc webhook rendering", "csi-clone", true, f.IsCSIVolumeCloneStorageClassAvailable),
|
||||
Entry("[test_id:10993]should do snapshot clone if possible", "snapshot", false, f.IsSnapshotStorageClassAvailable),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10994]should do snapshot clone if possible, with pvc webhook rendering", Serial, "snapshot", true, f.IsSnapshotStorageClassAvailable),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10994]should do snapshot clone if possible, with pvc webhook rendering", "snapshot", true, f.IsSnapshotStorageClassAvailable),
|
||||
Entry("[test_id:10995]should do host assisted clone", "copy", false, nil),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10996]should do host assisted clone, with pvc webhook rendering", Serial, "copy", true, nil),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10996]should do host assisted clone, with pvc webhook rendering", "copy", true, nil),
|
||||
)
|
||||
})
|
||||
|
||||
@ -394,7 +388,7 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
Expect(same).To(BeTrue())
|
||||
},
|
||||
Entry("[test_id:10997]with valid target PVC", false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10998]with incomplete target PVC webhook rendering", Serial, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:10998]with incomplete target PVC webhook rendering", true),
|
||||
)
|
||||
|
||||
Context("Fallback to host assisted", func() {
|
||||
@ -433,7 +427,7 @@ var _ = Describe("Clone Populator tests", func() {
|
||||
f.ExpectCloneFallback(target, clone.NoVolumeExpansion, clone.MessageNoVolumeExpansion)
|
||||
},
|
||||
Entry("[test_id:10999]with valid target PVC", false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11000]with incomplete target PVC webhook rendering", Serial, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11000]with incomplete target PVC webhook rendering", true),
|
||||
)
|
||||
|
||||
It("should finish the clone after creating the source snapshot", func() {
|
||||
|
@ -13,7 +13,6 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
core "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
@ -215,12 +214,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
return utils.NewDataVolumeWithImageioWarmImport(dataVolumeName, size, url, s.Name, cm, diskID, checkpoints, true)
|
||||
}
|
||||
|
||||
updateWebhookPvcRendering := func(webhookRenderingLabel string) {
|
||||
if webhookRenderingLabel == "true" {
|
||||
EnableWebhookPvcRendering(f.CrClient)
|
||||
}
|
||||
}
|
||||
|
||||
AfterEach(func() {
|
||||
if sourcePvc != nil {
|
||||
By("[AfterEach] Clean up sourcePvc PVC")
|
||||
@ -2064,8 +2057,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
origSpec.DeepCopyInto(config)
|
||||
})
|
||||
|
||||
DisableWebhookPvcRendering(f.CrClient)
|
||||
|
||||
Eventually(func() bool {
|
||||
config, err = f.CdiClient.CdiV1beta1().CDIConfigs().Get(context.TODO(), common.ConfigName, metav1.GetOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -2173,8 +2164,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
}
|
||||
|
||||
DescribeTable("Import fails creating a PVC from DV without accessModes and volume mode, no profile", func(webhookRenderingLabel string, verifyEvent func(string) bool) {
|
||||
updateWebhookPvcRendering(webhookRenderingLabel)
|
||||
|
||||
// assumes local is available and has no volumeMode
|
||||
storageProfileName := findStorageProfileWithoutAccessModes(f.CrClient)
|
||||
By(fmt.Sprintf("creating new datavolume %s without accessModes", dataVolumeName))
|
||||
@ -2209,12 +2198,10 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
}, timeout, pollingInterval).Should(BeTrue())
|
||||
},
|
||||
Entry("[test_id:5912] (controller rendering)", "false", verifyControllerRenderingEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11045] (webhook rendering)", Serial, "true", verifyWebhookRenderingEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11045] (webhook rendering)", "true", verifyWebhookRenderingEvent),
|
||||
)
|
||||
|
||||
DescribeTable("Import fails when no default storage class, and recovers when default is set", func(webhookRenderingLabel string, verifyEvent func(string) bool) {
|
||||
updateWebhookPvcRendering(webhookRenderingLabel)
|
||||
|
||||
By("updating to no default storage class")
|
||||
defaultSc.Annotations[controller.AnnDefaultStorageClass] = "false"
|
||||
defaultSc, err = f.K8sClient.StorageV1().StorageClasses().Update(context.TODO(), defaultSc, metav1.UpdateOptions{})
|
||||
@ -2258,12 +2245,10 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
},
|
||||
Entry("[test_id:8383] (controller rendering)", "false", verifyControllerRenderingNoDefaultScEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11046] (webhook rendering)", Serial, "true", verifyWebhookRenderingEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11046] (webhook rendering)", "true", verifyWebhookRenderingEvent),
|
||||
)
|
||||
|
||||
DescribeTable("Import recovers when user adds accessModes to profile", func(webhookRenderingLabel string, verifyEvent func(string) bool) {
|
||||
updateWebhookPvcRendering(webhookRenderingLabel)
|
||||
|
||||
// assumes local is available and has no volumeMode
|
||||
storageProfileName := findStorageProfileWithoutAccessModes(f.CrClient)
|
||||
By(fmt.Sprintf("creating new datavolume %s without accessModes", dataVolumeName))
|
||||
@ -2313,7 +2298,7 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
updateStorageProfileSpec(f.CrClient, storageProfileName, *originalProfileSpec)
|
||||
},
|
||||
Entry("[test_id:5913] (controller rendering)", "false", verifyControllerRenderingEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11047] (webhook rendering)", Serial, "true", verifyWebhookRenderingEvent),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11047] (webhook rendering)", "true", verifyWebhookRenderingEvent),
|
||||
)
|
||||
|
||||
It("[test_id:6483]Import pod should not have size corrected on block", func() {
|
||||
@ -2651,8 +2636,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
})
|
||||
pvName = ""
|
||||
}
|
||||
|
||||
DisableWebhookPvcRendering(f.CrClient)
|
||||
})
|
||||
|
||||
verifyControllerRenderingEventAndConditions := func(dv *cdiv1.DataVolume) {
|
||||
@ -2698,8 +2681,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
Skip("Default storage class has no provisioner. The new storage class won't work")
|
||||
}
|
||||
|
||||
updateWebhookPvcRendering(webhookRenderingLabel)
|
||||
|
||||
By(fmt.Sprintf("verifying no storage class %s", testScName))
|
||||
_, err := f.K8sClient.StorageV1().StorageClasses().Get(context.TODO(), scName, metav1.GetOptions{})
|
||||
Expect(err).To(HaveOccurred())
|
||||
@ -2735,9 +2716,9 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
Entry("[test_id:9922]the storage class is created (controller rendering)", "false", testScName, verifyControllerRenderingEventAndConditions, createStorageClass),
|
||||
Entry("[test_id:9924]PV with the SC name is created (controller rendering)", "false", testScName, verifyControllerRenderingEventAndConditions, createPV),
|
||||
Entry("[test_id:9925]PV with the SC name (\"\" blank) is created (controller rendering)", "false", "", verifyControllerRenderingEventAndConditions, createPV),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11049]the storage class is created (webhook rendering)", Serial, "true", testScName, verifyWebhookRenderingEventAndConditions, createStorageClass),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11050]PV with the SC name is created (webhook rendering)", Serial, "true", testScName, verifyWebhookRenderingEventAndConditions, createPV),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11051]PV with the SC name (\"\" blank) is created (webhook rendering)", Serial, "true", "", verifyWebhookRenderingEventAndConditions, createPV),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11049]the storage class is created (webhook rendering)", "true", testScName, verifyWebhookRenderingEventAndConditions, createStorageClass),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11050]PV with the SC name is created (webhook rendering)", "true", testScName, verifyWebhookRenderingEventAndConditions, createPV),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11051]PV with the SC name (\"\" blank) is created (webhook rendering)", "true", "", verifyWebhookRenderingEventAndConditions, createPV),
|
||||
)
|
||||
|
||||
newDataVolumeWithStorageSpec := func(scName string) *cdiv1.DataVolume {
|
||||
@ -2890,10 +2871,10 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests",
|
||||
Skip("Not HPP")
|
||||
}
|
||||
size := "1Gi"
|
||||
By("Verify No FeatureGates")
|
||||
By("Verify no WaitForFirstConsumer FeatureGate")
|
||||
config, err := f.CdiClient.CdiV1beta1().CDIConfigs().Get(context.TODO(), common.ConfigName, metav1.GetOptions{})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(config.Spec.FeatureGates).To(BeNil())
|
||||
Expect(config.Spec.FeatureGates).ShouldNot(ContainElements(featuregates.HonorWaitForFirstConsumer))
|
||||
|
||||
dataVolume := dvFunc(dvName, size, url())
|
||||
|
||||
@ -3560,28 +3541,3 @@ func SetFilesystemOverhead(f *framework.Framework, globalOverhead, scOverhead st
|
||||
return config.Status.FilesystemOverhead.StorageClass[defaultSCName] == cdiv1.Percent(globalOverhead)
|
||||
}, timeout, pollingInterval).Should(BeTrue(), "CDIConfig filesystem overhead wasn't set")
|
||||
}
|
||||
|
||||
func EnableWebhookPvcRendering(c client.Client) {
|
||||
By("enabling WebhookPvcRendering feature gate")
|
||||
_, err := utils.EnableFeatureGate(c, featuregates.WebhookPvcRendering)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Eventually(func() error {
|
||||
whc := &admissionregistrationv1.MutatingWebhookConfiguration{}
|
||||
return c.Get(context.TODO(), types.NamespacedName{Name: "cdi-api-pvc-mutate"}, whc)
|
||||
}, timeout, pollingInterval).ShouldNot(HaveOccurred())
|
||||
}
|
||||
|
||||
func DisableWebhookPvcRendering(c client.Client) {
|
||||
enabled, err := featuregates.IsWebhookPvcRenderingEnabled(c)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
if enabled {
|
||||
By("disabling WebhookPvcRendering feature gate")
|
||||
_, err := utils.DisableFeatureGate(c, featuregates.WebhookPvcRendering)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
Eventually(func() bool {
|
||||
whc := &admissionregistrationv1.MutatingWebhookConfiguration{}
|
||||
err := c.Get(context.TODO(), types.NamespacedName{Name: "cdi-api-pvc-mutate"}, whc)
|
||||
return err != nil && k8serrors.IsNotFound(err)
|
||||
}, timeout, pollingInterval).Should(BeTrue())
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ type Framework struct {
|
||||
// cannot work when called during test tree construction.
|
||||
func NewFramework(prefix string, config ...Config) *Framework {
|
||||
cfg := Config{
|
||||
FeatureGates: []string{featuregates.HonorWaitForFirstConsumer},
|
||||
FeatureGates: []string{featuregates.HonorWaitForFirstConsumer, featuregates.WebhookPvcRendering},
|
||||
}
|
||||
if len(config) > 0 {
|
||||
cfg = config[0]
|
||||
|
@ -1539,15 +1539,12 @@ var _ = Describe("Import populator", func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
pvc = nil
|
||||
}
|
||||
|
||||
tests.DisableWebhookPvcRendering(f.CrClient)
|
||||
})
|
||||
|
||||
DescribeTable("should import fileSystem PVC", func(expectedMD5 string, volumeImportSourceFunc func(cdiv1.DataVolumeContentType, bool) error, preallocation, webhookRendering bool) {
|
||||
pvc = importPopulationPVCDefinition()
|
||||
|
||||
if webhookRendering {
|
||||
tests.EnableWebhookPvcRendering(f.CrClient)
|
||||
controller.AddLabel(pvc, common.PvcApplyStorageProfileLabel, "true")
|
||||
// Unset AccessModes which will be set by the webhook rendering
|
||||
pvc.Spec.AccessModes = nil
|
||||
@ -1604,7 +1601,7 @@ var _ = Describe("Import populator", func() {
|
||||
},
|
||||
Entry("[test_id:11001]with HTTP image and preallocation", utils.TinyCoreMD5, createHTTPImportPopulatorCR, true, false),
|
||||
Entry("[test_id:11002]with HTTP image without preallocation", utils.TinyCoreMD5, createHTTPImportPopulatorCR, false, false),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11003]with HTTP image and preallocation, with incomplete PVC webhook rendering", Serial, utils.TinyCoreMD5, createHTTPImportPopulatorCR, true, true),
|
||||
Entry("[rfe_id:10985][crit:high][test_id:11003]with HTTP image and preallocation, with incomplete PVC webhook rendering", utils.TinyCoreMD5, createHTTPImportPopulatorCR, true, true),
|
||||
Entry("[test_id:11004]with Registry image and preallocation", utils.TinyCoreMD5, createRegistryImportPopulatorCR, true, false),
|
||||
Entry("[test_id:11005]with Registry image without preallocation", utils.TinyCoreMD5, createRegistryImportPopulatorCR, false, false),
|
||||
Entry("[test_id:11006]with ImageIO image with preallocation", Label("ImageIO"), Serial, utils.ImageioMD5, createImageIOImportPopulatorCR, true, false),
|
||||
|
Loading…
Reference in New Issue
Block a user