mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

* Set the WaitForFirstConsumer phase on DataVolume when storage uses the WaitForFirstConsumer binding mode and is not bound yet. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Skip PVC if not bound in import|clone|upload controllers. This is done so the VM pod(not the cdi pod) will be the first consumer, and the PVC can be scheduled on the same location as the pod. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> fixup! Skip PVC if not bound in import|clone|upload controllers. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update importer tests to force bind the PCV by scheduling a pod for pvc, when storage class is wffc. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update datavolume tests to force bind the PCV by scheduling a pod for pvc, when storage class is wffc. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update upload controller and upload tests to correctly handle force binding the PCV by scheduling a pod for pvc, when storage class is wffc. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update clone tests to force bind the PCV by scheduling a pod for pvc when the storage class is wffc. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update cloner multi-node tests to force bind the PCV by scheduling a pod for pvc when storage class is wffc. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Correct after automerge Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Improve/simplify tests Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Fix error in import test. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update transport_test,operator_test.go Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update rbac_test.go and leaderelection_test.go Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Improve Datavolume and PVC Checks for WFFC. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Handle wffc only if feature gate is open - import-controller Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * TEST for Handle wffc only if feature gate is open - import-controller - TEST Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Handle wffc only if feature gate is open - upload-controller with test Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * rename and simplify checks Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * cleanup after rebase Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * update tests after rebase Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * update tests after rebase Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * more cleanups Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Document new WFFC behavior Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Document new HonorWaitForFirstConsumer option Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * update docs according to comments Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * extract common function, cleanup - code review fixes Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * add comment for another pr - 1210, so it can have easier merge/rebase Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * typo Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Simplify getStoragebindingMode - code review comments Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Add FeatureGates interface - code review fix Additionally pass the features gates instead of the particular feature gate value, and let shouldReconcilePVC decide what to do with the feature gate. That way shouldReconcilePVC contains all the logic, and the caller does not need to do additional calls to provide parameters. Signed-off-by: Bartosz Rybacki <brybacki@redhat.com> * Update matcher Signed-off-by: Bartosz Rybacki <brybacki@redhat.com>
280 lines
7.4 KiB
Go
280 lines
7.4 KiB
Go
package tests
|
|
|
|
import (
|
|
"reflect"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/ginkgo/extensions/table"
|
|
. "github.com/onsi/gomega"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
rbacv1 "k8s.io/api/rbac/v1"
|
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
|
|
cdiClientset "kubevirt.io/containerized-data-importer/pkg/client/clientset/versioned"
|
|
"kubevirt.io/containerized-data-importer/tests/framework"
|
|
"kubevirt.io/containerized-data-importer/tests/utils"
|
|
)
|
|
|
|
var _ = Describe("Aggregated role in-action tests", func() {
|
|
var createServiceAccount = func(client kubernetes.Interface, namespace, name string) {
|
|
sa := &corev1.ServiceAccount{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: name,
|
|
},
|
|
}
|
|
|
|
_, err := client.CoreV1().ServiceAccounts(namespace).Create(sa)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
|
|
var createRoleBinding = func(client kubernetes.Interface, clusterRoleName, namespace, serviceAccount string) {
|
|
rb := &rbacv1.RoleBinding{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: serviceAccount,
|
|
},
|
|
RoleRef: rbacv1.RoleRef{
|
|
Kind: "ClusterRole",
|
|
Name: clusterRoleName,
|
|
APIGroup: "rbac.authorization.k8s.io",
|
|
},
|
|
Subjects: []rbacv1.Subject{
|
|
{
|
|
Kind: "ServiceAccount",
|
|
Name: serviceAccount,
|
|
Namespace: namespace,
|
|
},
|
|
},
|
|
}
|
|
|
|
_, err := client.RbacV1().RoleBindings(namespace).Create(rb)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
|
|
f := framework.NewFrameworkOrDie("aggregated-role-tests")
|
|
|
|
DescribeTable("admin/edit datavolume permission checks", func(user string) {
|
|
var client *cdiClientset.Clientset
|
|
var err error
|
|
|
|
createServiceAccount(f.K8sClient, f.Namespace.Name, user)
|
|
createRoleBinding(f.K8sClient, user, f.Namespace.Name, user)
|
|
|
|
Eventually(func() error {
|
|
client, err = f.GetCdiClientForServiceAccount(f.Namespace.Name, user)
|
|
return err
|
|
}, 60*time.Second, 2*time.Second).ShouldNot(HaveOccurred())
|
|
|
|
dv := utils.NewDataVolumeWithHTTPImport("test-"+user, "1Gi", "http://nonexistant.url")
|
|
dv, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(dv)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dvl, err := client.CdiV1beta1().DataVolumes(f.Namespace.Name).List(metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(HaveLen(1))
|
|
|
|
dv, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Get(dv.Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Delete(dv.Name, &metav1.DeleteOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dvl, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).List(metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(HaveLen(0))
|
|
|
|
dv = utils.NewDataVolumeForUpload("upload-test-"+user, "1Gi")
|
|
dv, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(dv)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
var pvc *corev1.PersistentVolumeClaim
|
|
Eventually(func() error {
|
|
pvc, err = f.K8sClient.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Get(dv.Name, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}, 90*time.Second, 2*time.Second).ShouldNot(HaveOccurred())
|
|
f.ForceBindPvcIfDvIsWaitForFirstConsumer(dv)
|
|
|
|
found, err := utils.WaitPVCPodStatusRunning(f.K8sClient, pvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(found).Should(BeTrue())
|
|
|
|
token, err := utils.RequestUploadToken(client, pvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(token).ToNot(BeEmpty())
|
|
|
|
cl, err := client.CdiV1beta1().CDIConfigs().List(metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(cl.Items).To(HaveLen(1))
|
|
|
|
cfg, err := client.CdiV1beta1().CDIConfigs().Get(cl.Items[0].Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
cfg.Spec.ScratchSpaceStorageClass = &[]string{"foobar"}[0]
|
|
cfg, err = client.CdiV1beta1().CDIConfigs().Update(cfg)
|
|
Expect(err).To(HaveOccurred())
|
|
},
|
|
Entry("[test_id:3948]can do everything with admin", "admin"),
|
|
Entry("[test_id:3949]can do everything with edit", "edit"),
|
|
)
|
|
|
|
It("[test_id:3950]view datavolume permission checks", func() {
|
|
const user = "view"
|
|
var client cdiClientset.Interface
|
|
var err error
|
|
|
|
createServiceAccount(f.K8sClient, f.Namespace.Name, user)
|
|
createRoleBinding(f.K8sClient, user, f.Namespace.Name, user)
|
|
|
|
Eventually(func() error {
|
|
client, err = f.GetCdiClientForServiceAccount(f.Namespace.Name, user)
|
|
return err
|
|
}, 60*time.Second, 2*time.Second).ShouldNot(HaveOccurred())
|
|
|
|
dv := utils.NewDataVolumeWithHTTPImport("test-"+user, "1Gi", "http://nonexistant.url")
|
|
dv, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(dv)
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
dvl, err := client.CdiV1beta1().DataVolumes(f.Namespace.Name).List(metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(HaveLen(0))
|
|
|
|
_, err = client.CdiV1beta1().DataVolumes(f.Namespace.Name).Get("test-"+user, metav1.GetOptions{})
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(k8serrors.IsNotFound(err)).To(BeTrue())
|
|
|
|
cl, err := client.CdiV1beta1().CDIConfigs().List(metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(cl.Items).To(HaveLen(1))
|
|
|
|
cfg, err := client.CdiV1beta1().CDIConfigs().Get(cl.Items[0].Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
cfg.Spec.ScratchSpaceStorageClass = &[]string{"foobar"}[0]
|
|
cfg, err = client.CdiV1beta1().CDIConfigs().Update(cfg)
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Aggregated role definition tests", func() {
|
|
var adminRules = []rbacv1.PolicyRule{
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes",
|
|
},
|
|
Verbs: []string{
|
|
"*",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes/source",
|
|
},
|
|
Verbs: []string{
|
|
"create",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"cdiconfigs",
|
|
},
|
|
Verbs: []string{
|
|
"get",
|
|
"list",
|
|
"watch",
|
|
"patch",
|
|
"update",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"upload.cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"uploadtokenrequests",
|
|
},
|
|
Verbs: []string{
|
|
"*",
|
|
},
|
|
},
|
|
}
|
|
|
|
var editRules = adminRules
|
|
|
|
var viewRules = []rbacv1.PolicyRule{
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes",
|
|
},
|
|
Verbs: []string{
|
|
"get",
|
|
"list",
|
|
"watch",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes/source",
|
|
},
|
|
Verbs: []string{
|
|
"create",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"cdiconfigs",
|
|
},
|
|
Verbs: []string{
|
|
"get",
|
|
"list",
|
|
"watch",
|
|
},
|
|
},
|
|
}
|
|
|
|
f := framework.NewFrameworkOrDie("aggregated-role-definition-tests")
|
|
|
|
DescribeTable("check all expected rules exist", func(role string, rules []rbacv1.PolicyRule) {
|
|
clusterRole, err := f.K8sClient.RbacV1().ClusterRoles().Get(role, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
found := false
|
|
for _, expectedRule := range rules {
|
|
for _, r := range clusterRole.Rules {
|
|
if reflect.DeepEqual(expectedRule, r) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
Expect(found).To(BeTrue())
|
|
},
|
|
Entry("[test_id:3945]for admin", "admin", adminRules),
|
|
Entry("[test_id:3946]for edit", "edit", editRules),
|
|
Entry("[test_id:3947]for view", "view", viewRules),
|
|
)
|
|
})
|