Skip to content

Commit f28d08e

Browse files
authored
Merge pull request #559 from jingxu97/July/test
update driver test code for Windows
2 parents 42e18f7 + e928fa2 commit f28d08e

File tree

8 files changed

+265
-29
lines changed

8 files changed

+265
-29
lines changed

deploy/kubernetes/base/controller/cluster_setup.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ kind: ServiceAccount
44
metadata:
55
name: csi-gce-pd-node-sa
66

7+
---
8+
##### Node Service Account, Roles, RoleBindings
9+
apiVersion: v1
10+
kind: ServiceAccount
11+
metadata:
12+
name: csi-gce-pd-node-sa-win
13+
714
---
815
##### Controller Service Account, Roles, Rolebindings
916
apiVersion: v1
@@ -195,7 +202,7 @@ roleRef:
195202
name: csi-gce-pd-node-deploy-win
196203
subjects:
197204
- kind: ServiceAccount
198-
name: csi-gce-pd-node-sa
205+
name: csi-gce-pd-node-sa-win
199206

200207
---
201208
apiVersion: rbac.authorization.k8s.io/v1

deploy/kubernetes/images/alpha/image.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ metadata:
1515
imageTag:
1616
name: gke.gcr.io/k8s-staging-csi/csi-node-driver-registrar-win
1717
newName: gcr.io/k8s-staging-csi/csi-node-driver-registrar
18-
newTag: "amd64-windows-v20200428-v1.3.0-26-g510710d5"
18+
newTag: "amd64-windows-canary"

test/k8s-integration/driver-config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func generateDriverConfigFile(platform, pkgDir, storageClassFile, snapshotClassF
4545

4646
// Fill in template parameters. Capabilities can be found here:
4747
// https://github.com/kubernetes/kubernetes/blob/b717be8269a4f381ab6c23e711e8924bc1f64c93/test/e2e/storage/testsuites/testdriver.go#L136
48+
4849
caps := []string{
4950
"persistence",
5051
"block",
@@ -56,6 +57,12 @@ func generateDriverConfigFile(platform, pkgDir, storageClassFile, snapshotClassF
5657
var fsTypes []string
5758
if platform == "windows" {
5859
fsTypes = []string{"ntfs"}
60+
caps = []string{
61+
"persistence",
62+
"exec",
63+
"multipods",
64+
"topology",
65+
}
5966
} else {
6067
fsTypes = []string{
6168
"ext2",

test/k8s-integration/driver.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ import (
88
"path/filepath"
99
"time"
1010

11+
"k8s.io/klog"
1112
"k8s.io/kubernetes/test/e2e/framework/podlogs"
1213
)
1314

1415
func getOverlayDir(pkgDir, deployOverlayName string) string {
1516
return filepath.Join(pkgDir, "deploy", "kubernetes", "overlays", deployOverlayName)
1617
}
1718

18-
func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
19+
func installDriver(platform, goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
1920
if doDriverBuild {
2021
// Install kustomize
22+
klog.Infof("Installing kustomize")
2123
out, err := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
2224
if err != nil {
2325
return fmt.Errorf("failed to install kustomize: %s, err: %v", out, err)
@@ -41,6 +43,17 @@ func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayNa
4143
if err != nil {
4244
return fmt.Errorf("failed to edit kustomize: %s, err: %v", out, err)
4345
}
46+
if platform == "windows" {
47+
out, err = exec.Command(
48+
filepath.Join(pkgDir, "bin", "kustomize"),
49+
"edit",
50+
"set",
51+
"image",
52+
fmt.Sprintf("%s-win=%s-win:%s", pdImagePlaceholder, stagingImage, stagingVersion)).CombinedOutput()
53+
if err != nil {
54+
return fmt.Errorf("failed to edit kustomize: %s, err: %v", out, err)
55+
}
56+
}
4457
}
4558

4659
// setup service account file for secret creation
@@ -65,11 +78,18 @@ func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayNa
6578
if err != nil {
6679
return fmt.Errorf("failed to deploy driver: %v", err)
6780
}
68-
81+
klog.Infof("Deploying driver")
6982
// TODO (#139): wait for driver to be running
70-
time.Sleep(time.Minute)
71-
statusCmd := exec.Command("kubectl", "describe", "pods", "-n", driverNamespace)
72-
err = runCommand("Checking driver pods", statusCmd)
83+
if platform == "windows" {
84+
klog.Infof("Waiting 15 minutes for the driver to start on Windows")
85+
time.Sleep(15 * time.Minute)
86+
} else {
87+
klog.Infof("Waiting 5 minutes for the driver to start on Linux")
88+
time.Sleep(5 * time.Minute)
89+
}
90+
out, err = exec.Command("kubectl", "describe", "pods", "-n", driverNamespace).CombinedOutput()
91+
klog.Infof("describe pods \n %s", string(out))
92+
7393
if err != nil {
7494
return fmt.Errorf("failed to describe pods: %v", err)
7595
}
@@ -99,18 +119,22 @@ func pushImage(pkgDir, stagingImage, stagingVersion, platform string) error {
99119
return err
100120
}
101121
var cmd *exec.Cmd
102-
if platform != "windows" {
103-
cmd = exec.Command("make", "-C", pkgDir, "push-container",
104-
fmt.Sprintf("GCE_PD_CSI_STAGING_VERSION=%s", stagingVersion),
105-
fmt.Sprintf("GCE_PD_CSI_STAGING_IMAGE=%s", stagingImage))
106-
} else {
107-
cmd = exec.Command("make", "-C", pkgDir, "build-and-push-windows-container-1909",
108-
fmt.Sprintf("GCE_PD_CSI_STAGING_VERSION=%s", stagingVersion),
109-
fmt.Sprintf("GCE_PD_CSI_STAGING_IMAGE=%s", stagingImage))
110-
}
111-
err = runCommand("Pushing GCP Container", cmd)
122+
123+
cmd = exec.Command("make", "-C", pkgDir, "push-container",
124+
fmt.Sprintf("GCE_PD_CSI_STAGING_VERSION=%s", stagingVersion),
125+
fmt.Sprintf("GCE_PD_CSI_STAGING_IMAGE=%s", stagingImage))
126+
err = runCommand("Pushing GCP Container for Linux", cmd)
112127
if err != nil {
113-
return fmt.Errorf("failed to run make command: err: %v", err)
128+
return fmt.Errorf("failed to run make command for linux: err: %v", err)
129+
}
130+
if platform == "windows" {
131+
cmd = exec.Command("make", "-C", pkgDir, "build-and-push-windows-container-ltsc2019",
132+
fmt.Sprintf("GCE_PD_CSI_STAGING_VERSION=%s", stagingVersion),
133+
fmt.Sprintf("GCE_PD_CSI_STAGING_IMAGE=%s-win", stagingImage))
134+
err = runCommand("Building and Pushing GCP Container for Windows", cmd)
135+
if err != nil {
136+
return fmt.Errorf("failed to run make command for windows: err: %v", err)
137+
}
114138
}
115139
return nil
116140
}

test/k8s-integration/main.go

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ func init() {
7979
}
8080

8181
func main() {
82+
klog.InitFlags(nil)
83+
flag.Set("logtostderr", "true")
8284
flag.Parse()
8385

8486
if !*inProw && *doDriverBuild {
@@ -298,27 +300,41 @@ func handle() error {
298300
}
299301
}()
300302
}
303+
301304
// For windows cluster, when cluster is up, all Windows nodes are tainted with NoSchedule to avoid linux pods
302305
// being scheduled to Windows nodes. When running windows tests, we need to remove the taint.
303306
if *platform == "windows" {
304-
nodesCmd := exec.Command("kubectl", "get", "nodes", "-l", "beta.kubernetes.io/os=windows", "-o", "name")
307+
nodesCmd := exec.Command("kubectl", "get", "nodes", "-l", "kubernetes.io/os=windows", "-o", "name")
305308
out, err := nodesCmd.CombinedOutput()
306309
if err != nil {
307-
return fmt.Errorf("failed to get nodes: %v", err)
310+
return fmt.Errorf("failed to get windows nodes: %v", err)
308311
}
309312
nodes := strings.Fields(string(out))
310313
for _, node := range nodes {
311314
taintCmd := exec.Command("kubectl", "taint", "node", node, "node.kubernetes.io/os:NoSchedule-")
312-
_, err = taintCmd.CombinedOutput()
315+
out, err := taintCmd.CombinedOutput()
313316
if err != nil {
314317
return fmt.Errorf("failed to untaint windows node %v", err)
315318
}
319+
klog.Infof("untaint windows nodes: %s, output %s", node, string(out))
320+
}
321+
322+
// It typically takes 5+ minutes to download Windows container image. To avoid tests being timed out,
323+
// pre-pulling the test images as best effort.
324+
klog.Infof("Prepulling test images.")
325+
err = os.Setenv("PREPULL_IMAGE", filepath.Join(pkgDir, "test", "k8s-integration", "prepull.yaml"))
326+
if err != nil {
327+
return err
328+
}
329+
out, err = exec.Command(filepath.Join(pkgDir, "test", "k8s-integration", "prepull-image.sh")).CombinedOutput()
330+
if err != nil {
331+
return fmt.Errorf("failed to prepull images: %s, err: %v", out, err)
316332
}
317333
}
318334

319335
if !*useGKEManagedDriver {
320336
// Install the driver and defer its teardown
321-
err := installDriver(goPath, pkgDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
337+
err := installDriver(*platform, goPath, pkgDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
322338
if *teardownDriver {
323339
defer func() {
324340
if teardownErr := deleteDriver(goPath, pkgDir, *deployOverlayName); teardownErr != nil {
@@ -342,6 +358,30 @@ func handle() error {
342358
}()
343359
}
344360

361+
// For windows cluster, it has both Windows nodes and Linux nodes. Before triggering the tests, taint Linux nodes
362+
// with NoSchedule to avoid test pods being scheduled on Linux. Need to do this step after driver is deployed.
363+
// Also the test framework will not proceed to run tests unless all nodes are ready
364+
// AND schedulable. Allow not-ready nodes since we make Linux nodes
365+
// unschedulable.
366+
allowedNotReadyNodes := 0
367+
if *platform == "windows" {
368+
nodesCmd := exec.Command("kubectl", "get", "nodes", "-l", "kubernetes.io/os=linux", "-o", "name")
369+
out, err := nodesCmd.CombinedOutput()
370+
if err != nil {
371+
return fmt.Errorf("failed to get linux nodes: %v", err)
372+
}
373+
nodes := strings.Fields(string(out))
374+
allowedNotReadyNodes = len(nodes)
375+
for _, node := range nodes {
376+
taintCmd := exec.Command("kubectl", "taint", "node", node, "node.kubernetes.io/os:NoSchedule")
377+
out, err := taintCmd.CombinedOutput()
378+
if err != nil {
379+
return fmt.Errorf("failed to untaint windows node %v", err)
380+
}
381+
klog.Infof("taint linux nodes: %s, output %s", node, string(out))
382+
}
383+
}
384+
345385
var cloudProviderArgs []string
346386
var err error
347387
switch *deploymentStrat {
@@ -374,7 +414,8 @@ func handle() error {
374414
for _, scFile := range storageClasses {
375415
outputDir := strings.TrimSuffix(scFile, ".yaml")
376416
testOutputDirs = append(testOutputDirs, outputDir)
377-
if err = runCSITests(*platform, pkgDir, testDir, *testFocus, testSkip, scFile, *snapshotClassFile, cloudProviderArgs, *deploymentStrat, outputDir); err != nil {
417+
if err = runCSITests(*platform, pkgDir, testDir, *testFocus, testSkip, scFile,
418+
*snapshotClassFile, cloudProviderArgs, *deploymentStrat, outputDir, allowedNotReadyNodes); err != nil {
378419
ginkgoErrors = append(ginkgoErrors, err.Error())
379420
}
380421
}
@@ -455,19 +496,20 @@ func setEnvProject(project string) error {
455496
}
456497

457498
func runMigrationTests(pkgDir, testDir, testFocus, testSkip string, cloudProviderArgs []string) error {
458-
return runTestsWithConfig(testDir, testFocus, testSkip, "--storage.migratedPlugins=kubernetes.io/gce-pd", cloudProviderArgs, "")
499+
return runTestsWithConfig(testDir, testFocus, testSkip, "--storage.migratedPlugins=kubernetes.io/gce-pd", cloudProviderArgs, "", 0)
459500
}
460501

461-
func runCSITests(platform, pkgDir, testDir, testFocus, testSkip, storageClassFile, snapshotClassFile string, cloudProviderArgs []string, deploymentStrat, reportPrefix string) error {
502+
func runCSITests(platform, pkgDir, testDir, testFocus, testSkip, storageClassFile, snapshotClassFile string,
503+
cloudProviderArgs []string, deploymentStrat, reportPrefix string, allowedNotReadyNodes int) error {
462504
testDriverConfigFile, err := generateDriverConfigFile(platform, pkgDir, storageClassFile, snapshotClassFile, deploymentStrat)
463505
if err != nil {
464506
return err
465507
}
466508
testConfigArg := fmt.Sprintf("--storage.testdriver=%s", testDriverConfigFile)
467-
return runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg, cloudProviderArgs, reportPrefix)
509+
return runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg, cloudProviderArgs, reportPrefix, allowedNotReadyNodes)
468510
}
469511

470-
func runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg string, cloudProviderArgs []string, reportPrefix string) error {
512+
func runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg string, cloudProviderArgs []string, reportPrefix string, allowedNotReadyNodes int) error {
471513
err := os.Chdir(testDir)
472514
if err != nil {
473515
return err
@@ -494,7 +536,7 @@ func runTestsWithConfig(testDir, testFocus, testSkip, testConfigArg string, clou
494536
}
495537
ginkgoArgs := fmt.Sprintf("--ginkgo.focus=%s --ginkgo.skip=%s", testFocus, testSkip)
496538
if *platform == "windows" {
497-
ginkgoArgs = ginkgoArgs + fmt.Sprintf(" --node-os-distro=%s", *platform)
539+
ginkgoArgs = ginkgoArgs + fmt.Sprintf(" --node-os-distro=%s --allowed-not-ready-nodes=%d", *platform, allowedNotReadyNodes)
498540
}
499541
testArgs := fmt.Sprintf("%s %s %s",
500542
ginkgoArgs,

test/k8s-integration/prepull-image.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
set -o nounset
4+
set -o pipefail
5+
set -o xtrace
6+
7+
if [[ -z "${PREPULL_IMAGE}" ]]; then
8+
# Pre-pull all the test images. The images are currently hard-coded.
9+
# Eventually, we should get the list directly from
10+
# https://github.com/kubernetes-sigs/windows-testing/blob/master/images/PullImages.ps1
11+
curl https://raw.githubusercontent.com/kubernetes-sigs/windows-testing/master/gce/prepull-1.18.yaml -o prepull.yaml
12+
PREPULL_IMAGE=prepull.yaml
13+
echo ${PREPULL_IMAGE}
14+
fi
15+
16+
kubectl create -f ${PREPULL_IMAGE}
17+
# Wait 10 minutes for the test images to be pulled onto the nodes.
18+
sleep 15m
19+
echo "sleep 15m"
20+
# Check the status of the pods.
21+
kubectl get pods -o wide
22+
# Delete the pods anyway since pre-pulling is best-effort
23+
kubectl delete -f ${PREPULL_IMAGE}
24+
# Wait a few more minutes for the pod to be cleaned up.
25+
sleep 5m

0 commit comments

Comments
 (0)