@@ -17,6 +17,7 @@ package main
17
17
import (
18
18
"flag"
19
19
"fmt"
20
+ "io/ioutil"
20
21
"os"
21
22
"os/exec"
22
23
"path/filepath"
@@ -36,11 +37,12 @@ var (
36
37
teardownDriver = flag .Bool ("teardown-driver" , true , "teardown the driver after the e2e test" )
37
38
bringupCluster = flag .Bool ("bringup-cluster" , true , "build kubernetes and bringup a cluster" )
38
39
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" )
40
42
kubeFeatureGates = flag .String ("kube-feature-gates" , "" , "feature gates to set on new kubernetes cluster" )
41
43
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" )
44
46
45
47
// Test infrastructure flags
46
48
boskosResourceType = flag .String ("boskos-resource-type" , "gce-project" , "name of the boskos resource type to reserve" )
@@ -67,43 +69,62 @@ const (
67
69
func init () {
68
70
flag .Set ("logtostderr" , "true" )
69
71
}
70
- func main () {
71
- flag .Parse ()
72
72
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 )
75
78
}
79
+ }
76
80
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 )
79
84
}
85
+ }
80
86
81
- if len (* deployOverlayName ) == 0 {
82
- klog .Fatalf ("deploy-overlay-name is a required flag" )
83
- }
87
+ func main () {
88
+ flag .Parse ()
84
89
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 " )
87
92
}
88
93
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" )
91
103
}
92
104
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" )
95
107
}
96
108
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." )
99
113
}
100
114
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
+ }
103
123
}
104
124
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." )
107
128
}
108
129
109
130
err := handle ()
@@ -122,10 +143,10 @@ func handle() error {
122
143
if ! ok {
123
144
return fmt .Errorf ("Could not find env variable GOPATH" )
124
145
}
146
+
125
147
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" )
128
148
149
+ // If running in Prow, then acquire and set up a project through Boskos
129
150
if * inProw {
130
151
project , _ := testutils .SetupProwConfig (* boskosResourceType )
131
152
@@ -157,69 +178,134 @@ func handle() error {
157
178
}
158
179
}
159
180
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.
160
241
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
+ }()
165
245
defer func () {
166
246
if * teardownCluster {
167
- err = deleteImage (* stagingImage , stagingVersion )
247
+ err : = deleteImage (* stagingImage , stagingVersion )
168
248
if err != nil {
169
249
klog .Errorf ("failed to delete image: %v" , err )
170
250
}
171
251
}
172
252
}()
253
+ } else {
254
+ errChan <- nil
173
255
}
174
256
175
257
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
193
262
}
194
- } else {
195
- klog .Errorf ("could not find cluster kubectl at %s, falling back to default kubectl" , kshPath )
196
- }
197
263
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
+ }
205
278
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
+ }
220
287
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
221
306
}
222
307
308
+ // Defer the tear down of the cluster through GKE or GCE
223
309
if * teardownCluster {
224
310
defer func () {
225
311
switch * deploymentStrat {
@@ -239,7 +325,21 @@ func handle() error {
239
325
}()
240
326
}
241
327
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 )
243
343
if * teardownDriver {
244
344
defer func () {
245
345
// TODO (#140): collect driver logs
@@ -252,14 +352,11 @@ func handle() error {
252
352
return fmt .Errorf ("failed to install CSI Driver: %v" , err )
253
353
}
254
354
255
- if len (* localK8sDir ) != 0 {
256
- k8sDir = * localK8sDir
257
- }
258
-
355
+ // Run the tests using the testDir kubernetes
259
356
if len (* storageClassFile ) != 0 {
260
- err = runCSITests (pkgDir , k8sDir , * testFocus , * storageClassFile , * gceZone )
357
+ err = runCSITests (pkgDir , testDir , * testFocus , * storageClassFile , * gceZone )
261
358
} else if * migrationTest {
262
- err = runMigrationTests (pkgDir , k8sDir , * testFocus , * gceZone )
359
+ err = runMigrationTests (pkgDir , testDir , * testFocus , * gceZone )
263
360
} else {
264
361
return fmt .Errorf ("Did not run either CSI or Migration test" )
265
362
}
@@ -420,7 +517,7 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
420
517
return filepath .Join (pkgDir , "deploy" , "kubernetes" , "overlays" , deployOverlayName )
421
518
}
422
519
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 {
424
521
if doDriverBuild {
425
522
// Install kustomize
426
523
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
449
546
}
450
547
451
548
// 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 ))
456
551
457
552
// Need to copy it to name the file "cloud-sa.json"
458
553
out , err := exec .Command ("cp" , * saFile , tmpSaFile ).CombinedOutput ()
@@ -602,3 +697,18 @@ func deleteImage(stagingImage, stagingVersion string) error {
602
697
}
603
698
return nil
604
699
}
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