From b6b25c80dec45eb98200d510a2c14d92d777a140 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Wed, 17 Aug 2022 10:38:25 +0200 Subject: [PATCH 1/2] e2e storage: add CreateFile to pod IO operations This complements the other operations and will be used by some future tests. --- test/e2e/storage/drivers/proxy/io.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/e2e/storage/drivers/proxy/io.go b/test/e2e/storage/drivers/proxy/io.go index 74fb6e1fa48..296ed882b11 100644 --- a/test/e2e/storage/drivers/proxy/io.go +++ b/test/e2e/storage/drivers/proxy/io.go @@ -18,6 +18,7 @@ package proxy import ( "fmt" + "io" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/storage/drivers/csi-test/mock/service" @@ -37,7 +38,7 @@ func (p PodDirIO) DirExists(path string) (bool, error) { "sh", "-c", fmt.Sprintf("if ! [ -e '%s' ]; then echo notexist; elif [ -d '%s' ]; then echo dir; else echo nodir; fi", path, path), - }) + }, nil) if err != nil { return false, fmt.Errorf("error executing dir test commands: stderr=%q, %v", stderr, err) } @@ -54,27 +55,36 @@ func (p PodDirIO) DirExists(path string) (bool, error) { } func (p PodDirIO) Mkdir(path string) error { - _, stderr, err := p.execute([]string{"mkdir", path}) + _, stderr, err := p.execute([]string{"mkdir", path}, nil) if err != nil { return fmt.Errorf("mkdir %q: stderr=%q, %v", path, stderr, err) } return nil } +func (p PodDirIO) CreateFile(path string, content io.Reader) error { + _, stderr, err := p.execute([]string{"dd", "of=" + path}, content) + if err != nil { + return fmt.Errorf("dd of=%s: stderr=%q, %v", path, stderr, err) + } + return nil +} + func (p PodDirIO) RemoveAll(path string) error { - _, stderr, err := p.execute([]string{"rm", "-rf", path}) + _, stderr, err := p.execute([]string{"rm", "-rf", path}, nil) if err != nil { return fmt.Errorf("rm -rf %q: stderr=%q, %v", path, stderr, err) } return nil } -func (p PodDirIO) execute(command []string) (string, string, error) { +func (p PodDirIO) execute(command []string, stdin io.Reader) (string, string, error) { return p.F.ExecWithOptions(framework.ExecOptions{ Command: command, Namespace: p.Namespace, PodName: p.PodName, ContainerName: p.ContainerName, + Stdin: stdin, CaptureStdout: true, CaptureStderr: true, Quiet: true, From 24230b4307f99f39785d91b1b0eacb14499fcf5a Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Wed, 17 Aug 2022 14:03:45 +0200 Subject: [PATCH 2/2] e2e storage: support creating ReplicaSet This is useful for running a driver on a subset of all ready nodes: - use e2enode.GetBoundedReadySchedulableNodes with a suitable maximum number of nodes to determine how much nodes are available for a test - define pod anti-affinity in the PodTemplate: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app.kubernetes.io/instance: xxxxxxx topologyKey: kubernetes.io/hostname - set the ReplicaSetSpec.Replicas value to the number of nodes --- test/e2e/storage/utils/create.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/e2e/storage/utils/create.go b/test/e2e/storage/utils/create.go index 46d823d8482..e23a191d4b0 100644 --- a/test/e2e/storage/utils/create.go +++ b/test/e2e/storage/utils/create.go @@ -275,6 +275,7 @@ var factories = map[What]ItemFactory{ {"ClusterRoleBinding"}: &clusterRoleBindingFactory{}, {"CSIDriver"}: &csiDriverFactory{}, {"DaemonSet"}: &daemonSetFactory{}, + {"ReplicaSet"}: &replicaSetFactory{}, {"Role"}: &roleFactory{}, {"RoleBinding"}: &roleBindingFactory{}, {"Secret"}: &secretFactory{}, @@ -382,6 +383,14 @@ func patchItemRecursively(f *framework.Framework, driverNamespace *v1.Namespace, if err := patchContainerImages(item.Spec.Template.Spec.InitContainers); err != nil { return err } + case *appsv1.ReplicaSet: + PatchNamespace(f, driverNamespace, &item.ObjectMeta.Namespace) + if err := patchContainerImages(item.Spec.Template.Spec.Containers); err != nil { + return err + } + if err := patchContainerImages(item.Spec.Template.Spec.InitContainers); err != nil { + return err + } case *apiextensionsv1.CustomResourceDefinition: // Do nothing. Patching name to all CRDs won't always be the expected behavior. default: @@ -584,6 +593,27 @@ func (*daemonSetFactory) Create(f *framework.Framework, ns *v1.Namespace, i inte }, nil } +type replicaSetFactory struct{} + +func (f *replicaSetFactory) New() runtime.Object { + return &appsv1.ReplicaSet{} +} + +func (*replicaSetFactory) Create(f *framework.Framework, ns *v1.Namespace, i interface{}) (func() error, error) { + item, ok := i.(*appsv1.ReplicaSet) + if !ok { + return nil, errorItemNotSupported + } + + client := f.ClientSet.AppsV1().ReplicaSets(ns.Name) + if _, err := client.Create(context.TODO(), item, metav1.CreateOptions{}); err != nil { + return nil, fmt.Errorf("create ReplicaSet: %w", err) + } + return func() error { + return client.Delete(context.TODO(), item.GetName(), metav1.DeleteOptions{}) + }, nil +} + type storageClassFactory struct{} func (f *storageClassFactory) New() runtime.Object {