@@ -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,56 @@ 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" )
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" )
92
98
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" )
95
103
}
96
104
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 " )
99
107
}
100
108
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
+ }
103
117
}
104
118
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." )
107
122
}
108
123
109
124
err := handle ()
@@ -122,10 +137,10 @@ func handle() error {
122
137
if ! ok {
123
138
return fmt .Errorf ("Could not find env variable GOPATH" )
124
139
}
140
+
125
141
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
142
143
+ // If running in Prow, then acquire and set up a project through Boskos
129
144
if * inProw {
130
145
project , _ := testutils .SetupProwConfig (* boskosResourceType )
131
146
@@ -157,69 +172,134 @@ func handle() error {
157
172
}
158
173
}
159
174
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.
160
235
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
+ }()
165
239
defer func () {
166
240
if * teardownCluster {
167
- err = deleteImage (* stagingImage , stagingVersion )
241
+ err : = deleteImage (* stagingImage , stagingVersion )
168
242
if err != nil {
169
243
klog .Errorf ("failed to delete image: %v" , err )
170
244
}
171
245
}
172
246
}()
247
+ } else {
248
+ errChan <- nil
173
249
}
174
250
175
251
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
193
256
}
194
- } else {
195
- klog .Errorf ("could not find cluster kubectl at %s, falling back to default kubectl" , kshPath )
196
- }
197
257
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
+ }
205
272
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
+ }
220
281
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
221
300
}
222
301
302
+ // Defer the tear down of the cluster through GKE or GCE
223
303
if * teardownCluster {
224
304
defer func () {
225
305
switch * deploymentStrat {
@@ -239,7 +319,21 @@ func handle() error {
239
319
}()
240
320
}
241
321
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 )
243
337
if * teardownDriver {
244
338
defer func () {
245
339
// TODO (#140): collect driver logs
@@ -252,14 +346,11 @@ func handle() error {
252
346
return fmt .Errorf ("failed to install CSI Driver: %v" , err )
253
347
}
254
348
255
- if len (* localK8sDir ) != 0 {
256
- k8sDir = * localK8sDir
257
- }
258
-
349
+ // Run the tests using the testDir kubernetes
259
350
if len (* storageClassFile ) != 0 {
260
- err = runCSITests (pkgDir , k8sDir , * testFocus , * storageClassFile , * gceZone )
351
+ err = runCSITests (pkgDir , testDir , * testFocus , * storageClassFile , * gceZone )
261
352
} else if * migrationTest {
262
- err = runMigrationTests (pkgDir , k8sDir , * testFocus , * gceZone )
353
+ err = runMigrationTests (pkgDir , testDir , * testFocus , * gceZone )
263
354
} else {
264
355
return fmt .Errorf ("Did not run either CSI or Migration test" )
265
356
}
@@ -420,7 +511,7 @@ func getOverlayDir(pkgDir, deployOverlayName string) string {
420
511
return filepath .Join (pkgDir , "deploy" , "kubernetes" , "overlays" , deployOverlayName )
421
512
}
422
513
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 {
424
515
if doDriverBuild {
425
516
// Install kustomize
426
517
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
449
540
}
450
541
451
542
// 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 ))
456
545
457
546
// Need to copy it to name the file "cloud-sa.json"
458
547
out , err := exec .Command ("cp" , * saFile , tmpSaFile ).CombinedOutput ()
@@ -602,3 +691,18 @@ func deleteImage(stagingImage, stagingVersion string) error {
602
691
}
603
692
return nil
604
693
}
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