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

* Enable gofmt linter From the docs: > Gofmt checks whether code was gofmt-ed. By default this tool runs with > -s option to check for code simplification. https://golangci-lint.run/usage/linters/#gofmt Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> * Run gomft on the project Ran this command after adding the gofmt linter: golangci-lint run ./... --fix Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> * Enable whitespace linter From the docs: > Whitespace is a linter that checks for unnecessary newlines at the > start and end of functions, if, for, etc. https://golangci-lint.run/usage/linters/#whitespace Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> * Run whitespace on the project Ran this command after adding the whitespace linter: golangci-lint run ./... --fix Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> * Enable GCI linter Per the docs: > Gci controls Go package import order and makes it always deterministic. https://golangci-lint.run/usage/linters/#gci NOTE: I noticed that many files separate their imports in a particular way, so I set the linter to enforce this standard. Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> * Run GCI on the project Ran this command after adding the GCI linter: golangci-lint run ./... --fix Signed-off-by: Edu Gómez Escandell <egomez@redhat.com> --------- Signed-off-by: Edu Gómez Escandell <egomez@redhat.com>
303 lines
9.3 KiB
Go
303 lines
9.3 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "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"
|
|
"k8s.io/client-go/kubernetes/scheme"
|
|
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
|
|
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", Serial, func() {
|
|
var createServiceAccount = func(client kubernetes.Interface, namespace, name string) {
|
|
sa := &corev1.ServiceAccount{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: name,
|
|
},
|
|
}
|
|
|
|
_, err := client.CoreV1().ServiceAccounts(namespace).Create(context.TODO(), sa, metav1.CreateOptions{})
|
|
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(context.TODO(), rb, metav1.CreateOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
}
|
|
|
|
f := framework.NewFramework("aggregated-role-tests")
|
|
|
|
DescribeTable("admin/edit datavolume permission checks", func(user string) {
|
|
var cdiClient *cdiClientset.Clientset
|
|
var crClient client.Client
|
|
var err error
|
|
|
|
createServiceAccount(f.K8sClient, f.Namespace.Name, user)
|
|
createRoleBinding(f.K8sClient, user, f.Namespace.Name, user)
|
|
|
|
Eventually(func() error {
|
|
cdiClient, err = f.GetCdiClientForServiceAccount(f.Namespace.Name, user)
|
|
return err
|
|
}, 60*time.Second, 2*time.Second).ShouldNot(HaveOccurred())
|
|
|
|
rc, err := f.GetRESTConfigForServiceAccount(f.Namespace.Name, user)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
crClient, err = client.New(rc, client.Options{Scheme: scheme.Scheme})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dv := utils.NewDataVolumeWithHTTPImport("test-"+user, "1Gi", "http://nonexistant.url")
|
|
dv, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(context.TODO(), dv, metav1.CreateOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dvl, err := cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(HaveLen(1))
|
|
|
|
dv, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Get(context.TODO(), dv.Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Delete(context.TODO(), dv.Name, metav1.DeleteOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dvl, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(BeEmpty())
|
|
|
|
dv = utils.NewDataVolumeForUpload("upload-test-"+user, "1Gi")
|
|
dv, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(context.TODO(), dv, metav1.CreateOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
var pvc *corev1.PersistentVolumeClaim
|
|
Eventually(func() error {
|
|
pvc, err = f.K8sClient.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Get(context.TODO(), 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(cdiClient, pvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(token).ToNot(BeEmpty())
|
|
|
|
cl, err := cdiClient.CdiV1beta1().CDIConfigs().List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(cl.Items).To(HaveLen(1))
|
|
|
|
_, err = cdiClient.CdiV1beta1().CDIConfigs().Get(context.TODO(), cl.Items[0].Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = utils.UpdateCDIConfig(crClient, func(config *cdiv1.CDIConfigSpec) {
|
|
config.ScratchSpaceStorageClass = &[]string{"foobar"}[0]
|
|
})
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
profiles, err := cdiClient.CdiV1beta1().StorageProfiles().List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(profiles.Items).ToNot(BeEmpty())
|
|
|
|
profileName := profiles.Items[0].Name
|
|
storageProfile, err := cdiClient.CdiV1beta1().StorageProfiles().Get(context.TODO(), profileName, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
spec := &storageProfile.Spec
|
|
cs := cdiv1.CloneStrategyCsiClone
|
|
spec.CloneStrategy = &cs
|
|
err = utils.UpdateStorageProfile(crClient, profileName, *spec)
|
|
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 cdiClient cdiClientset.Interface
|
|
var crClient client.Client
|
|
var err error
|
|
|
|
createServiceAccount(f.K8sClient, f.Namespace.Name, user)
|
|
createRoleBinding(f.K8sClient, user, f.Namespace.Name, user)
|
|
|
|
Eventually(func() error {
|
|
cdiClient, err = f.GetCdiClientForServiceAccount(f.Namespace.Name, user)
|
|
return err
|
|
}, 60*time.Second, 2*time.Second).ShouldNot(HaveOccurred())
|
|
|
|
rc, err := f.GetRESTConfigForServiceAccount(f.Namespace.Name, user)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
crClient, err = client.New(rc, client.Options{Scheme: scheme.Scheme})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
dv := utils.NewDataVolumeWithHTTPImport("test-"+user, "1Gi", "http://nonexistant.url")
|
|
_, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Create(context.TODO(), dv, metav1.CreateOptions{})
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
dvl, err := cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(dvl.Items).To(BeEmpty())
|
|
|
|
_, err = cdiClient.CdiV1beta1().DataVolumes(f.Namespace.Name).Get(context.TODO(), "test-"+user, metav1.GetOptions{})
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(k8serrors.IsNotFound(err)).To(BeTrue())
|
|
|
|
cl, err := cdiClient.CdiV1beta1().CDIConfigs().List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(cl.Items).To(HaveLen(1))
|
|
|
|
_, err = cdiClient.CdiV1beta1().CDIConfigs().Get(context.TODO(), cl.Items[0].Name, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
err = utils.UpdateCDIConfig(crClient, func(config *cdiv1.CDIConfigSpec) {
|
|
config.ScratchSpaceStorageClass = &[]string{"foobar"}[0]
|
|
})
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
profiles, err := cdiClient.CdiV1beta1().StorageProfiles().List(context.TODO(), metav1.ListOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(profiles.Items).ToNot(BeEmpty())
|
|
|
|
profileName := profiles.Items[0].Name
|
|
storageProfile, err := cdiClient.CdiV1beta1().StorageProfiles().Get(context.TODO(), profileName, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
spec := &storageProfile.Spec
|
|
cs := cdiv1.CloneStrategyCsiClone
|
|
spec.CloneStrategy = &cs
|
|
err = utils.UpdateStorageProfile(crClient, profileName, *spec)
|
|
Expect(err).To(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Aggregated role definition tests", Serial, func() {
|
|
var adminRules = []rbacv1.PolicyRule{
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes",
|
|
"dataimportcrons",
|
|
"datasources",
|
|
"volumeimportsources",
|
|
"volumeuploadsources",
|
|
"volumeclonesources",
|
|
},
|
|
Verbs: []string{
|
|
"*",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes/source",
|
|
},
|
|
Verbs: []string{
|
|
"create",
|
|
},
|
|
},
|
|
{
|
|
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{
|
|
"cdiconfigs",
|
|
"dataimportcrons",
|
|
"datasources",
|
|
"datavolumes",
|
|
"objecttransfers",
|
|
"storageprofiles",
|
|
"volumeimportsources",
|
|
"volumeuploadsources",
|
|
"volumeclonesources",
|
|
},
|
|
Verbs: []string{
|
|
"get",
|
|
"list",
|
|
"watch",
|
|
},
|
|
},
|
|
{
|
|
APIGroups: []string{
|
|
"cdi.kubevirt.io",
|
|
},
|
|
Resources: []string{
|
|
"datavolumes/source",
|
|
},
|
|
Verbs: []string{
|
|
"create",
|
|
},
|
|
},
|
|
}
|
|
|
|
f := framework.NewFramework("aggregated-role-definition-tests")
|
|
|
|
DescribeTable("check all expected rules exist", func(role string, rules []rbacv1.PolicyRule) {
|
|
clusterRole, err := f.K8sClient.RbacV1().ClusterRoles().Get(context.TODO(), role, metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
Expect(clusterRole.Rules).To(ContainElements(rules))
|
|
},
|
|
Entry("[test_id:3945]for admin", "admin", adminRules),
|
|
Entry("[test_id:3946]for edit", "edit", editRules),
|
|
Entry("[test_id:3947]for view", "view", viewRules),
|
|
)
|
|
})
|