Skip to content

Commit 34d7d5e

Browse files
committed
multi-Svc test refactor
1 parent a55574d commit 34d7d5e

File tree

7 files changed

+1303
-23
lines changed

7 files changed

+1303
-23
lines changed

hack/run-e2e-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ then
7373
OPTS+=(-p)
7474
ginkgo -mod=mod "${OPTS[@]}" --focus="csi-block-vanilla-parallelized" tests/e2e
7575
else
76-
ginkgo -mod=mod "${OPTS[@]}" --focus="$FOCUS" tests/e2e
76+
ginkgo -mod=mod "${OPTS[@]}" --focus="$FOCUS" -r tests/e2e
7777
fi
7878

7979
# Checking for test status

tests/e2e/constants/kubernetes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const (
7878
Snapshotapigroup = "snapshot.storage.k8s.io"
7979
DefaultNginxStorageClassName = "nginx-sc"
8080
MountPath = "/usr/share/nginx/html"
81+
ServiceName = "nginx"
8182
SpsServiceName = "sps"
8283
SnapshotterContainerName = "csi-snapshotter"
8384
SshdPort = "22"

tests/e2e/k8testutil/util.go

Lines changed: 163 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,12 +2556,12 @@ func DeleteService(ns string, c clientset.Interface, service *v1.Service) {
25562556

25572557
// GetStatefulSetFromManifest creates a StatefulSet from the statefulset.yaml
25582558
// file present in the manifest path.
2559-
func GetStatefulSetFromManifest(e2eTestConfig *config.E2eTestConfig, ns string) *appsv1.StatefulSet {
2559+
func GetStatefulSetFromManifest(e2eTestConfig *config.TestInputData, ns string) *appsv1.StatefulSet {
25602560
ssManifestFilePath := filepath.Join(constants.ManifestPath, "statefulset.yaml")
25612561
framework.Logf("Parsing statefulset from %v", ssManifestFilePath)
25622562
ss, err := manifest.StatefulSetFromManifest(ssManifestFilePath, ns)
25632563
framework.ExpectNoError(err)
2564-
if e2eTestConfig.TestInput.TestBedInfo.WindowsEnv {
2564+
if e2eTestConfig.TestBedInfo.WindowsEnv {
25652565
ss.Spec.Template.Spec.Containers[0].Image = constants.WindowsImageOnMcr
25662566
ss.Spec.Template.Spec.Containers[0].Command = []string{"Powershell.exe"}
25672567
ss.Spec.Template.Spec.Containers[0].Args = []string{"-Command", constants.WindowsExecCmd}
@@ -3053,6 +3053,7 @@ func TrimQuotes(str string) string {
30533053
// Returns a de-serialized structured config data
30543054
func ReadConfigFromSecretString(cfg string) (config.E2eTestConfig, error) {
30553055
var config1 config.E2eTestConfig
3056+
var testInput config.TestInputData
30563057
var netPerm config.NetPermissionConfig
30573058
key, value := "", ""
30583059
var permissions vsanfstypes.VsanFileShareAccessType
@@ -3082,7 +3083,7 @@ func ReadConfigFromSecretString(cfg string) (config.E2eTestConfig, error) {
30823083
value = words[1]
30833084
// Remove trailing '"]' characters from value.
30843085
value = strings.TrimSuffix(value, "]")
3085-
config1.TestInput.Global.VCenterHostname = TrimQuotes(value)
3086+
testInput.Global.VCenterHostname = TrimQuotes(value)
30863087
fmt.Printf("Key: VirtualCenter, Value: %s\n", value)
30873088
}
30883089
continue
@@ -3093,47 +3094,47 @@ func ReadConfigFromSecretString(cfg string) (config.E2eTestConfig, error) {
30933094
switch key {
30943095
case "insecure-flag":
30953096
if strings.Contains(value, "true") {
3096-
config1.TestInput.Global.InsecureFlag = true
3097+
testInput.Global.InsecureFlag = true
30973098
} else {
3098-
config1.TestInput.Global.InsecureFlag = false
3099+
testInput.Global.InsecureFlag = false
30993100
}
31003101
case "cluster-id":
3101-
config1.TestInput.Global.ClusterID = value
3102+
testInput.Global.ClusterID = value
31023103
case "cluster-distribution":
3103-
config1.TestInput.Global.ClusterDistribution = value
3104+
testInput.Global.ClusterDistribution = value
31043105
case "user":
3105-
config1.TestInput.Global.User = value
3106+
testInput.Global.User = value
31063107
case "password":
3107-
config1.TestInput.Global.Password = value
3108+
testInput.Global.Password = value
31083109
case "datacenters":
3109-
config1.TestInput.Global.Datacenters = value
3110+
testInput.Global.Datacenters = value
31103111
case "port":
3111-
config1.TestInput.Global.VCenterPort = value
3112+
testInput.Global.VCenterPort = value
31123113
case "cnsregistervolumes-cleanup-intervalinmin":
3113-
config1.TestInput.Global.CnsRegisterVolumesCleanupIntervalInMin, strconvErr = strconv.Atoi(value)
3114+
testInput.Global.CnsRegisterVolumesCleanupIntervalInMin, strconvErr = strconv.Atoi(value)
31143115
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31153116
case "topology-categories":
3116-
config1.TestInput.Labels.TopologyCategories = value
3117+
testInput.Labels.TopologyCategories = value
31173118
case "global-max-snapshots-per-block-volume":
3118-
config1.TestInput.Snapshot.GlobalMaxSnapshotsPerBlockVolume, strconvErr = strconv.Atoi(value)
3119+
testInput.Snapshot.GlobalMaxSnapshotsPerBlockVolume, strconvErr = strconv.Atoi(value)
31193120
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31203121
case "csi-fetch-preferred-datastores-intervalinmin":
3121-
config1.TestInput.Global.CSIFetchPreferredDatastoresIntervalInMin, strconvErr = strconv.Atoi(value)
3122+
testInput.Global.CSIFetchPreferredDatastoresIntervalInMin, strconvErr = strconv.Atoi(value)
31223123
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31233124
case "query-limit":
3124-
config1.TestInput.Global.QueryLimit, strconvErr = strconv.Atoi(value)
3125+
testInput.Global.QueryLimit, strconvErr = strconv.Atoi(value)
31253126
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31263127
case "list-volume-threshold":
3127-
config1.TestInput.Global.ListVolumeThreshold, strconvErr = strconv.Atoi(value)
3128+
testInput.Global.ListVolumeThreshold, strconvErr = strconv.Atoi(value)
31283129
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31293130
case "ca-file":
3130-
config1.TestInput.Global.CaFile = value
3131+
testInput.Global.CaFile = value
31313132
case "supervisor-id":
3132-
config1.TestInput.Global.SupervisorID = value
3133+
testInput.Global.SupervisorID = value
31333134
case "targetvSANFileShareClusters":
3134-
config1.TestInput.Global.TargetVsanFileShareClusters = value
3135+
testInput.Global.TargetVsanFileShareClusters = value
31353136
case "fileVolumeActivated":
3136-
config1.TestInput.Global.FileVolumeActivated, strconvErr = strconv.ParseBool(value)
3137+
testInput.Global.FileVolumeActivated, strconvErr = strconv.ParseBool(value)
31373138
gomega.Expect(strconvErr).NotTo(gomega.HaveOccurred())
31383139
case "ips":
31393140
netPerm.Ips = value
@@ -3145,6 +3146,7 @@ func ReadConfigFromSecretString(cfg string) (config.E2eTestConfig, error) {
31453146
return config1, fmt.Errorf("unknown key %s in the input string", key)
31463147
}
31473148
}
3149+
config1.TestInput = &testInput
31483150
return config1, nil
31493151
}
31503152

@@ -5783,7 +5785,7 @@ func CreateParallelStatefulSets(client clientset.Interface, namespace string,
57835785
gomega.Expect(err).NotTo(gomega.HaveOccurred())
57845786
}
57855787

5786-
func CreateParallelStatefulSetSpec(e2eTestConfig *config.E2eTestConfig,
5788+
func CreateParallelStatefulSetSpec(e2eTestConfig *config.TestInputData,
57875789
namespace string, no_of_sts int, replicas int32) []*appsv1.StatefulSet {
57885790
stss := []*appsv1.StatefulSet{}
57895791
var statefulset *appsv1.StatefulSet
@@ -7315,3 +7317,142 @@ func ListStoragePolicyUsages(ctx context.Context, c clientset.Interface, restCli
73157317

73167318
fmt.Println("All required storage policy usages are available.")
73177319
}
7320+
7321+
// ExitHostMM exits a host from maintenance mode with a particular timeout
7322+
func ExitHostMM(ctx context.Context, host *object.HostSystem, timeout int32) {
7323+
task, err := host.ExitMaintenanceMode(ctx, timeout)
7324+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
7325+
7326+
_, err = task.WaitForResultEx(ctx, nil)
7327+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
7328+
7329+
framework.Logf("Host: %v exited from maintenance mode", host)
7330+
}
7331+
7332+
/*
7333+
createStafeulSetAndVerifyPVAndPodNodeAffinty creates user specified statefulset and
7334+
further checks the node and volumes affinities
7335+
*/
7336+
func CreateStafeulSetAndVerifyPVAndPodNodeAffinty(ctx context.Context, client clientset.Interface,
7337+
vs *config.E2eTestConfig, namespace string, parallelPodPolicy bool, replicas int32, nodeAffinityToSet bool,
7338+
allowedTopologies []v1.TopologySelectorLabelRequirement,
7339+
podAntiAffinityToSet bool, parallelStatefulSetCreation bool, modifyStsSpec bool,
7340+
accessMode v1.PersistentVolumeAccessMode,
7341+
sc *storagev1.StorageClass, verifyTopologyAffinity bool, storagePolicy string) (*v1.Service,
7342+
*appsv1.StatefulSet, error) {
7343+
7344+
ginkgo.By("Create service")
7345+
service := CreateService(namespace, client)
7346+
7347+
framework.Logf("Create StatefulSet")
7348+
statefulset := CreateCustomisedStatefulSets(ctx, client, vs.TestInput, namespace, parallelPodPolicy,
7349+
replicas, nodeAffinityToSet, allowedTopologies, podAntiAffinityToSet, modifyStsSpec,
7350+
"", accessMode, sc, storagePolicy)
7351+
7352+
if verifyTopologyAffinity {
7353+
framework.Logf("Verify PV node affinity and that the PODS are running on appropriate node")
7354+
err := VerifyPVnodeAffinityAndPODnodedetailsForStatefulsetsLevel5(ctx, vs, client, statefulset,
7355+
namespace, allowedTopologies, parallelStatefulSetCreation)
7356+
if err != nil {
7357+
return nil, nil, fmt.Errorf("error verifying PV node affinity and POD node details: %v", err)
7358+
}
7359+
}
7360+
7361+
return service, statefulset, nil
7362+
}
7363+
7364+
/*
7365+
createCustomisedStatefulSets util methods creates statefulset as per the user's
7366+
specific requirement and returns the customised statefulset
7367+
*/
7368+
func CreateCustomisedStatefulSets(ctx context.Context, client clientset.Interface, vs *config.TestInputData,
7369+
namespace string, isParallelPodMgmtPolicy bool, replicas int32, nodeAffinityToSet bool,
7370+
allowedTopologies []v1.TopologySelectorLabelRequirement,
7371+
podAntiAffinityToSet bool, modifyStsSpec bool, stsName string,
7372+
accessMode v1.PersistentVolumeAccessMode, sc *storagev1.StorageClass, storagePolicy string) *appsv1.StatefulSet {
7373+
framework.Logf("Preparing StatefulSet Spec")
7374+
statefulset := GetStatefulSetFromManifest(vs, namespace)
7375+
7376+
if accessMode == "" {
7377+
// If accessMode is not specified, set the default accessMode.
7378+
defaultAccessMode := v1.ReadWriteOnce
7379+
statefulset.Spec.VolumeClaimTemplates[len(statefulset.Spec.VolumeClaimTemplates)-1].
7380+
Spec.AccessModes[0] = defaultAccessMode
7381+
} else {
7382+
statefulset.Spec.VolumeClaimTemplates[len(statefulset.Spec.VolumeClaimTemplates)-1].Spec.AccessModes[0] =
7383+
accessMode
7384+
}
7385+
7386+
if modifyStsSpec {
7387+
if vs.TestBedInfo.MultipleSvc {
7388+
statefulset.Spec.VolumeClaimTemplates[len(statefulset.Spec.VolumeClaimTemplates)-1].
7389+
Spec.StorageClassName = &storagePolicy
7390+
} else {
7391+
statefulset.Spec.VolumeClaimTemplates[len(statefulset.Spec.VolumeClaimTemplates)-1].
7392+
Spec.StorageClassName = &sc.Name
7393+
}
7394+
7395+
if stsName != "" {
7396+
statefulset.Name = stsName
7397+
statefulset.Spec.Template.Labels["app"] = statefulset.Name
7398+
statefulset.Spec.Selector.MatchLabels["app"] = statefulset.Name
7399+
}
7400+
7401+
}
7402+
if nodeAffinityToSet {
7403+
nodeSelectorTerms := GetNodeSelectorTerms(allowedTopologies)
7404+
statefulset.Spec.Template.Spec.Affinity = new(v1.Affinity)
7405+
statefulset.Spec.Template.Spec.Affinity.NodeAffinity = new(v1.NodeAffinity)
7406+
statefulset.Spec.Template.Spec.Affinity.NodeAffinity.
7407+
RequiredDuringSchedulingIgnoredDuringExecution = new(v1.NodeSelector)
7408+
statefulset.Spec.Template.Spec.Affinity.NodeAffinity.
7409+
RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms = nodeSelectorTerms
7410+
}
7411+
if podAntiAffinityToSet {
7412+
statefulset.Spec.Template.Spec.Affinity = &v1.Affinity{
7413+
PodAntiAffinity: &v1.PodAntiAffinity{
7414+
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{
7415+
{
7416+
LabelSelector: &metav1.LabelSelector{
7417+
MatchLabels: map[string]string{
7418+
"key": "app",
7419+
},
7420+
},
7421+
TopologyKey: "topology.kubernetes.io/zone",
7422+
},
7423+
},
7424+
},
7425+
}
7426+
7427+
}
7428+
if isParallelPodMgmtPolicy {
7429+
statefulset.Spec.PodManagementPolicy = appsv1.ParallelPodManagement
7430+
}
7431+
statefulset.Spec.Replicas = &replicas
7432+
7433+
framework.Logf("Creating statefulset")
7434+
CreateStatefulSet(namespace, statefulset, client)
7435+
7436+
framework.Logf("Wait for StatefulSet pods to be in up and running state")
7437+
fss.WaitForStatusReadyReplicas(ctx, client, statefulset, replicas)
7438+
gomega.Expect(fss.CheckMount(ctx, client, statefulset, constants.MountPath)).NotTo(gomega.HaveOccurred())
7439+
ssPodsBeforeScaleDown, err := fss.GetPodList(ctx, client, statefulset)
7440+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
7441+
gomega.Expect(ssPodsBeforeScaleDown.Items).NotTo(gomega.BeEmpty(),
7442+
fmt.Sprintf("Unable to get list of Pods from the Statefulset: %v", statefulset.Name))
7443+
gomega.Expect(len(ssPodsBeforeScaleDown.Items) == int(replicas)).To(gomega.BeTrue(),
7444+
"Number of Pods in the statefulset should match with number of replicas")
7445+
7446+
return statefulset
7447+
}
7448+
7449+
// CreateStatefulSet creates a StatefulSet from the manifest at manifestPath in the given namespace.
7450+
func CreateStatefulSet(ns string, ss *appsv1.StatefulSet, c clientset.Interface) {
7451+
ctx, cancel := context.WithCancel(context.Background())
7452+
defer cancel()
7453+
framework.Logf("Creating statefulset %v/%v with %d replicas and selector %+v",
7454+
ss.Namespace, ss.Name, *(ss.Spec.Replicas), ss.Spec.Selector)
7455+
_, err := c.AppsV1().StatefulSets(ns).Create(ctx, ss, metav1.CreateOptions{})
7456+
framework.ExpectNoError(err)
7457+
fss.WaitForRunningAndReady(ctx, c, *ss.Spec.Replicas, ss)
7458+
}

0 commit comments

Comments
 (0)