Skip to content

Commit 8a4e02b

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

File tree

3 files changed

+226
-98
lines changed

3 files changed

+226
-98
lines changed

test/k8s-integration/main.go

+192-86
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,57 @@ 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-
}
8487

85-
if len(*storageClassFile) == 0 && !*migrationTest {
86-
klog.Fatalf("One of storageclass-file and migration-test must be set")
87-
}
88+
func main() {
89+
flag.Parse()
8890

89-
if len(*storageClassFile) != 0 && *migrationTest {
90-
klog.Fatalf("storage-class-file and migration-test cannot both be set")
91+
if !*inProw {
92+
ensureVariable(stagingImage, true, "staging-image is a required flag, please specify the name of image to stage to")
9193
}
9294

93-
if !*bringupCluster && len(*kubeFeatureGates) > 0 {
94-
klog.Fatalf("kube-feature-gates set but not bringing up new cluster")
95+
ensureVariable(saFile, true, "service-account-file is a required flag")
96+
ensureVariable(deployOverlayName, true, "deploy-overlay-name is a required flag")
97+
ensureVariable(testFocus, true, "test-focus is a required flag")
98+
ensureVariable(gceZone, true, "gce-zone is a required flag")
99+
100+
if *migrationTest{
101+
ensureVariable(storageClassFile, false, "storage-class-file and migration-test cannot both be set")
102+
} else {
103+
ensureVariable(storageClassFile, true, "One of storageclass-file and migration-test must be set")
95104
}
96105

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

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

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

109125
err := handle()
@@ -122,10 +138,10 @@ func handle() error {
122138
if !ok {
123139
return fmt.Errorf("Could not find env variable GOPATH")
124140
}
141+
125142
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")
128143

144+
// If running in Prow, then acquire and set up a project through Boskos
129145
if *inProw {
130146
project, _ := testutils.SetupProwConfig(*boskosResourceType)
131147

@@ -157,69 +173,134 @@ func handle() error {
157173
}
158174
}
159175

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

175252
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)
253+
go func(){
254+
if !(<- k8sDependencyChan){
255+
errChan <- nil
256+
return
193257
}
194-
} else {
195-
klog.Errorf("could not find cluster kubectl at %s, falling back to default kubectl", kshPath)
196-
}
197258

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

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

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

303+
// Defer the tear down of the cluster through GKE or GCE
223304
if *teardownCluster {
224305
defer func() {
225306
switch *deploymentStrat {
@@ -239,7 +320,21 @@ func handle() error {
239320
}()
240321
}
241322

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

255-
if len(*localK8sDir) != 0 {
256-
k8sDir = *localK8sDir
257-
}
258-
350+
// Run the tests using the testDir kubernetes
259351
if len(*storageClassFile) != 0 {
260-
err = runCSITests(pkgDir, k8sDir, *testFocus, *storageClassFile, *gceZone)
352+
err = runCSITests(pkgDir, testDir, *testFocus, *storageClassFile, *gceZone)
261353
} else if *migrationTest {
262-
err = runMigrationTests(pkgDir, k8sDir, *testFocus, *gceZone)
354+
err = runMigrationTests(pkgDir, testDir, *testFocus, *gceZone)
263355
} else {
264356
return fmt.Errorf("Did not run either CSI or Migration test")
265357
}
@@ -331,6 +423,7 @@ func runTestsWithConfig(pkgDir, k8sDir, gceZone, testFocus, testConfigArg string
331423
return nil
332424
}
333425

426+
334427
func runCommand(action string, cmd *exec.Cmd) error {
335428
cmd.Stdout = os.Stdout
336429
cmd.Stdin = os.Stdin
@@ -420,7 +513,7 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
420513
return filepath.Join(pkgDir, "deploy", "kubernetes", "overlays", deployOverlayName)
421514
}
422515

423-
func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
516+
func installDriver(goPath, pkgDir, stagingImage, stagingVersion, deployOverlayName string, doDriverBuild bool) error {
424517
if doDriverBuild {
425518
// Install kustomize
426519
out, err := exec.Command(filepath.Join(pkgDir, "deploy", "kubernetes", "install-kustomize.sh")).CombinedOutput()
@@ -449,10 +542,8 @@ func installDriver(goPath, pkgDir, k8sDir, stagingImage, stagingVersion, deployO
449542
}
450543

451544
// 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))
545+
tmpSaFile := filepath.Join(getTempDir(), "cloud-sa.json")
546+
defer removeTempDir(filepath.Dir(tmpSaFile))
456547

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

0 commit comments

Comments
 (0)