Skip to content

Commit 7be1b1d

Browse files
author
Hantao (Will) Wang
committed
add background building and flag to specify test version spearate from
kube version
1 parent e51e6d6 commit 7be1b1d

File tree

3 files changed

+229
-95
lines changed

3 files changed

+229
-95
lines changed

test/k8s-integration/main.go

+189-85
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package main
1717
import (
1818
"flag"
1919
"fmt"
20+
"io/ioutil"
2021
"os"
2122
"os/exec"
2223
"path/filepath"
@@ -36,11 +37,12 @@ var (
3637
teardownDriver = flag.Bool("teardown-driver", true, "teardown the driver after the e2e test")
3738
bringupCluster = flag.Bool("bringup-cluster", true, "build kubernetes and bringup a cluster")
3839
gceZone = flag.String("gce-zone", "", "zone that the gce k8s cluster is created/found in")
39-
kubeVersion = flag.String("kube-version", "master", "version of Kubernetes to download and use")
40+
kubeVersion = flag.String("kube-version", "", "version of Kubernetes to download and use for the cluster")
41+
testVersion = flag.String("test-version", "", "version of Kubernetes to download and use for tests")
4042
kubeFeatureGates = flag.String("kube-feature-gates", "", "feature gates to set on new kubernetes cluster")
4143
localK8sDir = flag.String("local-k8s-dir", "", "local kubernetes/kubernetes directory to run e2e tests from")
42-
deploymentStrat = flag.String("deployment-strategy", "gce", "choose between deploying on gce or gke")
43-
gkeClusterVer = flag.String("gke-cluster-version", "latest", "version of Kubernetes master and node for gke")
44+
deploymentStrat = flag.String("deployment-strategy", "", "choose between deploying on gce or gke")
45+
gkeClusterVer = flag.String("gke-cluster-version", "", "version of Kubernetes master and node for gke")
4446

4547
// Test infrastructure flags
4648
boskosResourceType = flag.String("boskos-resource-type", "gce-project", "name of the boskos resource type to reserve")
@@ -67,43 +69,56 @@ const (
6769
func init() {
6870
flag.Set("logtostderr", "true")
6971
}
70-
func main() {
71-
flag.Parse()
7272

73-
if len(*stagingImage) == 0 && !*inProw {
74-
klog.Fatalf("staging-image is a required flag, please specify the name of image to stage to")
73+
func ensureVariable(v *string, set bool, msgOnError string) {
74+
if set && len(*v) == 0 {
75+
klog.Fatal(msgOnError)
76+
} else if !set && len(*v) != 0 {
77+
klog.Fatal(msgOnError)
7578
}
79+
}
7680

77-
if len(*saFile) == 0 {
78-
klog.Fatalf("service-account-file is a required flag")
81+
func ensureFlag(v *bool, setTo bool, msgOnError string) {
82+
if *v != setTo {
83+
klog.Fatal(msgOnError)
7984
}
85+
}
8086

81-
if len(*deployOverlayName) == 0 {
82-
klog.Fatalf("deploy-overlay-name is a required flag")
83-
}
87+
func main() {
88+
flag.Parse()
8489

85-
if len(*storageClassFile) == 0 && !*migrationTest {
86-
klog.Fatalf("One of storageclass-file and migration-test must be set")
90+
if !*inProw {
91+
ensureVariable(stagingImage, true, "staging-image is a required flag, please specify the name of image to stage to")
8792
}
8893

89-
if len(*storageClassFile) != 0 && *migrationTest {
90-
klog.Fatalf("storage-class-file and migration-test cannot both be set")
91-
}
94+
ensureVariable(saFile, true, "service-account-file is a required flag")
95+
ensureVariable(deployOverlayName, true, "deploy-overlay-name is a required flag")
96+
ensureVariable(testFocus, true, "test-focus is a required flag")
97+
ensureVariable(gceZone, true, "gce-zone is a required flag")
9298

93-
if !*bringupCluster && len(*kubeFeatureGates) > 0 {
94-
klog.Fatalf("kube-feature-gates set but not bringing up new cluster")
99+
if *migrationTest {
100+
ensureVariable(storageClassFile, false, "storage-class-file and migration-test cannot both be set")
101+
} else {
102+
ensureVariable(storageClassFile, true, "One of storageclass-file and migration-test must be set")
95103
}
96104

97-
if len(*testFocus) == 0 {
98-
klog.Fatalf("test-focus is a required flag")
105+
if !*bringupCluster {
106+
ensureVariable(kubeFeatureGates, false, "kube-feature-gates set but not bringing up new cluster")
99107
}
100108

101-
if len(*gceZone) == 0 {
102-
klog.Fatalf("gce-zone is a required flag")
109+
if *deploymentStrat == "gke" {
110+
ensureFlag(migrationTest, false, "Cannot set deployment strategy to 'gke' for migration tests.")
111+
ensureVariable(kubeVersion, false, "Cannot set kube-version when using deployment strategy 'gke'. Use gke-cluster-version.")
112+
ensureVariable(gkeClusterVer, true, "Must set gke-cluster-version when using deployment strategy 'gke'.")
113+
ensureVariable(kubeFeatureGates, false, "Cannot set feature gates when using deployment strategy 'gke'.")
114+
if len(*localK8sDir) == 0 {
115+
ensureVariable(testVersion, true, "Must set either test-version or local k8s dir when using deployment strategy 'gke'.")
116+
}
103117
}
104118

105-
if *deploymentStrat == "gke" && *migrationTest {
106-
klog.Fatalf("Cannot set deployment strategy to 'gke' for migration tests.")
119+
if len(*localK8sDir) != 0 {
120+
ensureVariable(kubeVersion, false, "Cannot set a kube version when using a local k8s dir.")
121+
ensureVariable(testVersion, false, "Cannot set a test version when using a local k8s dir.")
107122
}
108123

109124
err := handle()
@@ -122,10 +137,10 @@ func handle() error {
122137
if !ok {
123138
return fmt.Errorf("Could not find env variable GOPATH")
124139
}
140+
125141
pkgDir := filepath.Join(goPath, "src", "sigs.k8s.io", "gcp-compute-persistent-disk-csi-driver")
126-
k8sIoDir := filepath.Join(pkgDir, "test", "k8s-integration", "src", "k8s.io")
127-
k8sDir := filepath.Join(k8sIoDir, "kubernetes")
128142

143+
// If running in Prow, then acquire and set up a project through Boskos
129144
if *inProw {
130145
project, _ := testutils.SetupProwConfig(*boskosResourceType)
131146

@@ -157,69 +172,134 @@ func handle() error {
157172
}
158173
}
159174

175+
// Create temporary directories for kubernetes builds
176+
k8sParentDir := getTempDir()
177+
k8sDir := filepath.Join(k8sParentDir, "kubernetes")
178+
testParentDir := getTempDir()
179+
testDir := filepath.Join(testParentDir, "kubernetes")
180+
defer removeTempDir(k8sParentDir)
181+
defer removeTempDir(testParentDir)
182+
183+
numTasks := 4
184+
errChan := make(chan error, numTasks)
185+
k8sDependencyChan := make(chan bool, 1)
186+
187+
// If kube version is set, then download and build Kubernetes for cluster creation
188+
// Otherwise, either GKE or a prebuild local K8s dir is being used
189+
if len(*kubeVersion) != 0 {
190+
go func() {
191+
err := downloadKubernetesSource(pkgDir, k8sParentDir, *kubeVersion)
192+
if err != nil {
193+
errChan <- fmt.Errorf("failed to download Kubernetes source: %v", err)
194+
k8sDependencyChan <- false
195+
return
196+
}
197+
err = buildKubernetes(k8sDir)
198+
if err != nil {
199+
errChan <- fmt.Errorf("failed to build Kubernetes: %v", err)
200+
k8sDependencyChan <- false
201+
return
202+
}
203+
k8sDependencyChan <- true
204+
errChan <- nil
205+
}()
206+
} else {
207+
errChan <- nil
208+
k8sDir = *localK8sDir
209+
k8sDependencyChan <- true
210+
}
211+
212+
// If test version is set, then download and build Kubernetes to run K8s tests
213+
// Otherwise, either kube version is set (which implies GCE) or a local K8s dir is being used
214+
if len(*testVersion) != 0 && *testVersion != *kubeVersion {
215+
go func() {
216+
// TODO: Build only the tests
217+
err := downloadKubernetesSource(pkgDir, testParentDir, *testVersion)
218+
if err != nil {
219+
errChan <- fmt.Errorf("failed to download Kubernetes source: %v", err)
220+
return
221+
}
222+
err = buildKubernetes(testDir)
223+
if err != nil {
224+
errChan <- fmt.Errorf("failed to build Kubernetes: %v", err)
225+
return
226+
}
227+
errChan <- nil
228+
}()
229+
} else {
230+
testDir = k8sDir
231+
errChan <- nil
232+
}
233+
234+
// Build and push the driver, if required. Defer the driver image deletion.
160235
if *doDriverBuild {
161-
err := pushImage(pkgDir, *stagingImage, stagingVersion)
162-
if err != nil {
163-
return fmt.Errorf("failed pushing image: %v", err)
164-
}
236+
go func() {
237+
errChan <- pushImage(pkgDir, *stagingImage, stagingVersion)
238+
}()
165239
defer func() {
166240
if *teardownCluster {
167-
err = deleteImage(*stagingImage, stagingVersion)
241+
err := deleteImage(*stagingImage, stagingVersion)
168242
if err != nil {
169243
klog.Errorf("failed to delete image: %v", err)
170244
}
171245
}
172246
}()
247+
} else {
248+
errChan <- nil
173249
}
174250

175251
if *bringupCluster {
176-
err := downloadKubernetesSource(pkgDir, k8sIoDir, *kubeVersion)
177-
if err != nil {
178-
return fmt.Errorf("failed to download Kubernetes source: %v", err)
179-
}
180-
181-
err = buildKubernetes(k8sDir)
182-
if err != nil {
183-
return fmt.Errorf("failed to build Kubernetes: %v", err)
184-
}
185-
186-
kshPath := filepath.Join(k8sDir, "cluster", "kubectl.sh")
187-
_, err = os.Stat(kshPath)
188-
if err == nil {
189-
// Set kubectl to the one bundled in the k8s tar for versioning
190-
err = os.Setenv("GCE_PD_KUBECTL", kshPath)
191-
if err != nil {
192-
return fmt.Errorf("failed to set cluster specific kubectl: %v", err)
252+
go func() {
253+
if !(<-k8sDependencyChan) {
254+
errChan <- nil
255+
return
193256
}
194-
} else {
195-
klog.Errorf("could not find cluster kubectl at %s, falling back to default kubectl", kshPath)
196-
}
197257

198-
if len(*kubeFeatureGates) != 0 {
199-
err = os.Setenv("KUBE_FEATURE_GATES", *kubeFeatureGates)
200-
if err != nil {
201-
return fmt.Errorf("failed to set kubernetes feature gates: %v", err)
202-
}
203-
klog.V(4).Infof("Set Kubernetes feature gates: %v", *kubeFeatureGates)
204-
}
258+
switch *deploymentStrat {
259+
case "gce":
260+
kshPath := filepath.Join(k8sDir, "cluster", "kubectl.sh")
261+
_, err := os.Stat(kshPath)
262+
if err == nil {
263+
// Set kubectl to the one bundled in the k8s tar for versioning
264+
err = os.Setenv("GCE_PD_KUBECTL", kshPath)
265+
if err != nil {
266+
errChan <- fmt.Errorf("failed to set cluster specific kubectl: %v", err)
267+
return
268+
}
269+
} else {
270+
klog.Errorf("could not find cluster kubectl at %s, falling back to default kubectl", kshPath)
271+
}
205272

206-
switch *deploymentStrat {
207-
case "gce":
208-
err = clusterUpGCE(k8sDir, *gceZone)
209-
if err != nil {
210-
return fmt.Errorf("failed to cluster up: %v", err)
211-
}
212-
case "gke":
213-
err = clusterUpGKE(*gceZone)
214-
if err != nil {
215-
return fmt.Errorf("failed to cluster up: %v", err)
216-
}
217-
default:
218-
return fmt.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", *deploymentStrat)
219-
}
273+
if len(*kubeFeatureGates) != 0 {
274+
err = os.Setenv("KUBE_FEATURE_GATES", *kubeFeatureGates)
275+
if err != nil {
276+
errChan <- fmt.Errorf("failed to set kubernetes feature gates: %v", err)
277+
return
278+
}
279+
klog.V(4).Infof("Set Kubernetes feature gates: %v", *kubeFeatureGates)
280+
}
220281

282+
err = clusterUpGCE(k8sDir, *gceZone)
283+
if err != nil {
284+
errChan <- fmt.Errorf("failed to cluster up: %v", err)
285+
return
286+
}
287+
case "gke":
288+
err := clusterUpGKE(*gceZone)
289+
if err != nil {
290+
errChan <- fmt.Errorf("failed to cluster up: %v", err)
291+
return
292+
}
293+
default:
294+
errChan <- fmt.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", *deploymentStrat)
295+
}
296+
errChan <- nil
297+
}()
298+
} else {
299+
errChan <- nil
221300
}
222301

302+
// Defer the tear down of the cluster through GKE or GCE
223303
if *teardownCluster {
224304
defer func() {
225305
switch *deploymentStrat {
@@ -239,7 +319,21 @@ func handle() error {
239319
}()
240320
}
241321

242-
err := installDriver(goPath, pkgDir, k8sDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
322+
// Block until all background operations are complete
323+
var firstErr error = nil
324+
for i := 0; i < 4; i++ {
325+
if err := <-errChan; err != nil {
326+
if firstErr == nil {
327+
firstErr = err
328+
}
329+
}
330+
}
331+
if firstErr != nil {
332+
return firstErr
333+
}
334+
335+
// Install the driver and defer its teardown
336+
err := installDriver(goPath, pkgDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
243337
if *teardownDriver {
244338
defer func() {
245339
// TODO (#140): collect driver logs
@@ -252,14 +346,11 @@ func handle() error {
252346
return fmt.Errorf("failed to install CSI Driver: %v", err)
253347
}
254348

255-
if len(*localK8sDir) != 0 {
256-
k8sDir = *localK8sDir
257-
}
258-
349+
// Run the tests using the testDir kubernetes
259350
if len(*storageClassFile) != 0 {
260-
err = runCSITests(pkgDir, k8sDir, *testFocus, *storageClassFile, *gceZone)
351+
err = runCSITests(pkgDir, testDir, *testFocus, *storageClassFile, *gceZone)
261352
} else if *migrationTest {
262-
err = runMigrationTests(pkgDir, k8sDir, *testFocus, *gceZone)
353+
err = runMigrationTests(pkgDir, testDir, *testFocus, *gceZone)
263354
} else {
264355
return fmt.Errorf("Did not run either CSI or Migration test")
265356
}
@@ -420,7 +511,7 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
420511
return filepath.Join(pkgDir, "deploy", "kubernetes", "overlays", deployOverlayName)
421512
}
422513

423-
func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
514+
func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
424515
if doDriverBuild {
425516
// Install kustomize
426517
out, err := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
@@ -449,10 +540,8 @@ func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployO
449540
}
450541

451542
// setup service account file for secret creation
452-
tmpSaFile := fmt.Sprintf("/tmp/%s/cloud-sa.json", string(uuid.NewUUID()))
453-
454-
os.MkdirAll(filepath.Dir(tmpSaFile), 0750)
455-
defer os.Remove(filepath.Dir(tmpSaFile))
543+
tmpSaFile := filepath.Join(getTempDir(), "cloud-sa.json")
544+
defer removeTempDir(filepath.Dir(tmpSaFile))
456545

457546
// Need to copy it to name the file "cloud-sa.json"
458547
out, err := exec.Command("cp", *saFile, tmpSaFile).CombinedOutput()
@@ -602,3 +691,18 @@ func deleteImage(stagingImage, stagingVersion string) error {
602691
}
603692
return nil
604693
}
694+
695+
func getTempDir() string {
696+
dir, err := ioutil.TempDir("", "")
697+
if err != nil {
698+
klog.Fatalf("Error creating temp dir: %v", err)
699+
}
700+
return dir
701+
}
702+
703+
func removeTempDir(dir string) {
704+
err := os.RemoveAll(dir)
705+
if err != nil {
706+
klog.Fatalf("Error removing temp dir: %v", err)
707+
}
708+
}

0 commit comments

Comments
 (0)