Skip to content

Commit 319631b

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

File tree

3 files changed

+233
-94
lines changed

3 files changed

+233
-94
lines changed

test/k8s-integration/main.go

+194-84
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,62 @@ 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")
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")
98+
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")
91103
}
92104

93-
if !*bringupCluster && len(*kubeFeatureGates) > 0 {
94-
klog.Fatalf("kube-feature-gates set but not bringing up new cluster")
105+
if !*bringupCluster {
106+
ensureVariable(kubeFeatureGates, false, "kube-feature-gates set but not bringing up new cluster")
95107
}
96108

97-
if len(*testFocus) == 0 {
98-
klog.Fatalf("test-focus is a required flag")
109+
if *bringupCluster || *teardownCluster {
110+
ensureVariable(deploymentStrat, true, "Must set the deployment strategy if bringing up or down cluster.")
111+
} else {
112+
ensureVariable(deploymentStrat, false, "Cannot set the deployment strategy if not bringing up or down cluster.")
99113
}
100114

101-
if len(*gceZone) == 0 {
102-
klog.Fatalf("gce-zone is a required flag")
115+
if *deploymentStrat == "gke" {
116+
ensureFlag(migrationTest, false, "Cannot set deployment strategy to 'gke' for migration tests.")
117+
ensureVariable(kubeVersion, false, "Cannot set kube-version when using deployment strategy 'gke'. Use gke-cluster-version.")
118+
ensureVariable(gkeClusterVer, true, "Must set gke-cluster-version when using deployment strategy 'gke'.")
119+
ensureVariable(kubeFeatureGates, false, "Cannot set feature gates when using deployment strategy 'gke'.")
120+
if len(*localK8sDir) == 0 {
121+
ensureVariable(testVersion, true, "Must set either test-version or local k8s dir when using deployment strategy 'gke'.")
122+
}
103123
}
104124

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

109130
err := handle()
@@ -122,10 +143,10 @@ func handle() error {
122143
if !ok {
123144
return fmt.Errorf("Could not find env variable GOPATH")
124145
}
146+
125147
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")
128148

149+
// If running in Prow, then acquire and set up a project through Boskos
129150
if *inProw {
130151
project, _ := testutils.SetupProwConfig(*boskosResourceType)
131152

@@ -157,69 +178,134 @@ func handle() error {
157178
}
158179
}
159180

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

175257
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)
258+
go func() {
259+
if !(<-k8sDependencyChan) {
260+
errChan <- nil
261+
return
193262
}
194-
} else {
195-
klog.Errorf("could not find cluster kubectl at %s, falling back to default kubectl", kshPath)
196-
}
197263

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-
}
264+
switch *deploymentStrat {
265+
case "gce":
266+
kshPath := filepath.Join(k8sDir, "cluster", "kubectl.sh")
267+
_, err := os.Stat(kshPath)
268+
if err == nil {
269+
// Set kubectl to the one bundled in the k8s tar for versioning
270+
err = os.Setenv("GCE_PD_KUBECTL", kshPath)
271+
if err != nil {
272+
errChan <- fmt.Errorf("failed to set cluster specific kubectl: %v", err)
273+
return
274+
}
275+
} else {
276+
klog.Errorf("could not find cluster kubectl at %s, falling back to default kubectl", kshPath)
277+
}
205278

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-
}
279+
if len(*kubeFeatureGates) != 0 {
280+
err = os.Setenv("KUBE_FEATURE_GATES", *kubeFeatureGates)
281+
if err != nil {
282+
errChan <- fmt.Errorf("failed to set kubernetes feature gates: %v", err)
283+
return
284+
}
285+
klog.V(4).Infof("Set Kubernetes feature gates: %v", *kubeFeatureGates)
286+
}
220287

288+
err = clusterUpGCE(k8sDir, *gceZone)
289+
if err != nil {
290+
errChan <- fmt.Errorf("failed to cluster up: %v", err)
291+
return
292+
}
293+
case "gke":
294+
err := clusterUpGKE(*gceZone)
295+
if err != nil {
296+
errChan <- fmt.Errorf("failed to cluster up: %v", err)
297+
return
298+
}
299+
default:
300+
errChan <- fmt.Errorf("deployment-strategy must be set to 'gce' or 'gke', but is: %s", *deploymentStrat)
301+
}
302+
errChan <- nil
303+
}()
304+
} else {
305+
errChan <- nil
221306
}
222307

308+
// Defer the tear down of the cluster through GKE or GCE
223309
if *teardownCluster {
224310
defer func() {
225311
switch *deploymentStrat {
@@ -239,7 +325,21 @@ func handle() error {
239325
}()
240326
}
241327

242-
err := installDriver(goPath, pkgDir, k8sDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
328+
// Block until all background operations are complete
329+
var firstErr error = nil
330+
for i := 0; i < 4; i++ {
331+
if err := <-errChan; err != nil {
332+
if firstErr == nil {
333+
firstErr = err
334+
}
335+
}
336+
}
337+
if firstErr != nil {
338+
return firstErr
339+
}
340+
341+
// Install the driver and defer its teardown
342+
err := installDriver(goPath, pkgDir, *stagingImage, stagingVersion, *deployOverlayName, *doDriverBuild)
243343
if *teardownDriver {
244344
defer func() {
245345
// TODO (#140): collect driver logs
@@ -252,14 +352,11 @@ func handle() error {
252352
return fmt.Errorf("failed to install CSI Driver: %v", err)
253353
}
254354

255-
if len(*localK8sDir) != 0 {
256-
k8sDir = *localK8sDir
257-
}
258-
355+
// Run the tests using the testDir kubernetes
259356
if len(*storageClassFile) != 0 {
260-
err = runCSITests(pkgDir, k8sDir, *testFocus, *storageClassFile, *gceZone)
357+
err = runCSITests(pkgDir, testDir, *testFocus, *storageClassFile, *gceZone)
261358
} else if *migrationTest {
262-
err = runMigrationTests(pkgDir, k8sDir, *testFocus, *gceZone)
359+
err = runMigrationTests(pkgDir, testDir, *testFocus, *gceZone)
263360
} else {
264361
return fmt.Errorf("Did not run either CSI or Migration test")
265362
}
@@ -420,7 +517,7 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
420517
return filepath.Join(pkgDir, "deploy", "kubernetes", "overlays", deployOverlayName)
421518
}
422519

423-
func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
520+
func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
424521
if doDriverBuild {
425522
// Install kustomize
426523
out, err := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
@@ -449,10 +546,8 @@ func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployO
449546
}
450547

451548
// 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))
549+
tmpSaFile := filepath.Join(getTempDir(), "cloud-sa.json")
550+
defer removeTempDir(filepath.Dir(tmpSaFile))
456551

457552
// Need to copy it to name the file "cloud-sa.json"
458553
out, err := exec.Command("cp", *saFile, tmpSaFile).CombinedOutput()
@@ -602,3 +697,18 @@ func deleteImage(stagingImage, stagingVersion string) error {
602697
}
603698
return nil
604699
}
700+
701+
func getTempDir() string {
702+
dir, err := ioutil.TempDir("", "")
703+
if err != nil {
704+
klog.Fatalf("Error creating temp dir: %v", err)
705+
}
706+
return dir
707+
}
708+
709+
func removeTempDir(dir string) {
710+
err := os.RemoveAll(dir)
711+
if err != nil {
712+
klog.Fatalf("Error removing temp dir: %v", err)
713+
}
714+
}

0 commit comments

Comments
 (0)