Skip to content

Commit

Permalink
Add functional tests to cover the import populator flow
Browse files Browse the repository at this point in the history
This commit updates the import tests to cover the new import populator flow.

Signed-off-by: Alvaro Romero <alromero@redhat.com>
  • Loading branch information
alromeros committed Apr 17, 2023
1 parent 3db6b8a commit eee5a24
Show file tree
Hide file tree
Showing 6 changed files with 347 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pkg/controller/common/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,7 @@ func GetMetricsURL(pod *corev1.Pod) (string, error) {
return url, nil
}

// GetProgressReport fetches the progress report from the passed URL according to an specific regular expression
// GetProgressReportFromURL fetches the progress report from the passed URL according to an specific regular expression
func GetProgressReportFromURL(url string, regExp *regexp.Regexp, httpClient *http.Client) (string, error) {
resp, err := httpClient.Get(url)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/populators/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const (
// createdPVCPrimeSuccessfully provides a const to indicate we created PVC prime for population
createdPVCPrimeSuccessfully = "CreatedPVCPrimeSuccessfully"

// AnnSelectedNode annotation is added to a PVC that has been triggered by scheduler to
// be dynamically provisioned. Its value is the name of the selected node.
AnnSelectedNode = "volume.kubernetes.io/selected-node"

// annMigratedTo annotation is added to a PVC and PV that is supposed to be
// dynamically provisioned/deleted by by its corresponding CSI driver
// through the CSIMigration feature flags. When this annotation is set the
Expand Down
1 change: 1 addition & 0 deletions tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ go_test(
"//pkg/controller:go_default_library",
"//pkg/controller/common:go_default_library",
"//pkg/controller/datavolume:go_default_library",
"//pkg/controller/populators:go_default_library",
"//pkg/feature-gates:go_default_library",
"//pkg/image:go_default_library",
"//pkg/operator/resources/utils:go_default_library",
Expand Down
1 change: 1 addition & 0 deletions tests/framework/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ go_library(
"//pkg/client/clientset/versioned:go_default_library",
"//pkg/common:go_default_library",
"//pkg/controller/common:go_default_library",
"//pkg/controller/populators:go_default_library",
"//pkg/feature-gates:go_default_library",
"//pkg/image:go_default_library",
"//pkg/util/naming:go_default_library",
Expand Down
40 changes: 40 additions & 0 deletions tests/framework/pvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
controller "kubevirt.io/containerized-data-importer/pkg/controller/common"
"kubevirt.io/containerized-data-importer/pkg/controller/populators"
"kubevirt.io/containerized-data-importer/pkg/image"
"kubevirt.io/containerized-data-importer/pkg/util/naming"
"kubevirt.io/containerized-data-importer/tests/utils"
Expand All @@ -42,6 +43,19 @@ func (f *Framework) CreateBoundPVCFromDefinition(def *k8sv1.PersistentVolumeClai
return pvc
}

// CreateScheduledPVCFromDefinition is a wrapper around utils.CreatePVCFromDefinition that also triggeres
// the scheduler to dynamically provision a pvc with WaitForFirstConsumer storage class by
// executing f.ForceBindIfWaitForFirstConsumer(pvc)
func (f *Framework) CreateScheduledPVCFromDefinition(def *k8sv1.PersistentVolumeClaim) *k8sv1.PersistentVolumeClaim {
pvc, err := utils.CreatePVCFromDefinition(f.K8sClient, f.Namespace.Name, def)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
pvc, err = utils.WaitForPVC(f.K8sClient, pvc.Namespace, pvc.Name)
gomega.Expect(err).ToNot(gomega.HaveOccurred())

f.ForceSchedulingIfWaitForFirstConsumerPopulationPVC(pvc)
return pvc
}

// DeletePVC is a wrapper around utils.DeletePVC
func (f *Framework) DeletePVC(pvc *k8sv1.PersistentVolumeClaim) error {
return utils.DeletePVC(f.K8sClient, f.Namespace.Name, pvc.Name)
Expand Down Expand Up @@ -82,6 +96,13 @@ func (f *Framework) ForceBindIfWaitForFirstConsumer(targetPvc *k8sv1.PersistentV
}
}

// ForceSchedulingIfWaitForFirstConsumerPopulationPVC creates a Pod with the passed in PVC mounted under /dev/pvc, which forces the PVC to be scheduled for provisioning.
func (f *Framework) ForceSchedulingIfWaitForFirstConsumerPopulationPVC(targetPvc *k8sv1.PersistentVolumeClaim) {
if f.IsBindingModeWaitForFirstConsumer(targetPvc.Spec.StorageClassName) {
createConsumerPodForPopulationPVC(targetPvc, f)
}
}

func createConsumerPod(targetPvc *k8sv1.PersistentVolumeClaim, f *Framework) {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: creating \"consumer-pod\" to force binding PVC: %s\n", targetPvc.Name)
namespace := targetPvc.Namespace
Expand All @@ -101,6 +122,25 @@ func createConsumerPod(targetPvc *k8sv1.PersistentVolumeClaim, f *Framework) {
utils.DeletePodNoGrace(f.K8sClient, executorPod, namespace)
}

func createConsumerPodForPopulationPVC(targetPvc *k8sv1.PersistentVolumeClaim, f *Framework) {
fmt.Fprintf(ginkgo.GinkgoWriter, "INFO: creating \"consumer-pod\" to get 'selected-node' annotation on PVC: %s\n", targetPvc.Name)
namespace := targetPvc.Namespace

err := utils.WaitForPersistentVolumeClaimPhase(f.K8sClient, targetPvc.Namespace, k8sv1.ClaimPending, targetPvc.Name)
gomega.Expect(err).ToNot(gomega.HaveOccurred())

podName := naming.GetResourceName("consumer-pod", targetPvc.Name)
executorPod, err := f.CreateNoopPodWithPVC(podName, namespace, targetPvc)
gomega.Expect(err).ToNot(gomega.HaveOccurred())

selectedNode, status, err := utils.WaitForPVCAnnotation(f.K8sClient, namespace, targetPvc, populators.AnnSelectedNode)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(status).To(gomega.BeTrue())
gomega.Expect(selectedNode).ToNot(gomega.BeEmpty())

utils.DeletePodNoGrace(f.K8sClient, executorPod, namespace)
}

// VerifyPVCIsEmpty verifies a passed in PVC is empty, returns true if the PVC is empty, false if it is not. Optionaly, specify node for the pod.
func VerifyPVCIsEmpty(f *Framework, pvc *k8sv1.PersistentVolumeClaim, node string) (bool, error) {
var err error
Expand Down
Loading

0 comments on commit eee5a24

Please sign in to comment.