github.com/GoogleCloudPlatform/compute-image-tools/cli_tools@v0.0.0-20240516224744-de2dabc4ed1b/common/utils/param/populator_test.go (about) 1 // Copyright 2020 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package param 16 17 import ( 18 "errors" 19 "fmt" 20 "strings" 21 "testing" 22 23 "cloud.google.com/go/storage" 24 "github.com/golang/mock/gomock" 25 "github.com/stretchr/testify/assert" 26 27 daisy "github.com/GoogleCloudPlatform/compute-daisy" 28 29 "github.com/GoogleCloudPlatform/compute-image-tools/cli_tools/mocks" 30 ) 31 32 func TestPopulator_PopulateMissingParametersReturnsErrorWhenZoneCantBeRetrieved(t *testing.T) { 33 project := "a_project" 34 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 35 zone := "" 36 region := "" 37 file := "gs://a_bucket/a_file" 38 storageLocation := "US" 39 network := "original-network" 40 subnet := "original-subnet" 41 42 mockCtrl := gomock.NewController(t) 43 defer mockCtrl.Finish() 44 45 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 46 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 47 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 48 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 49 mockResourceLocationRetriever.EXPECT().GetZone("us-west2", project).Return("", 50 daisy.Errf("zone not found")).Times(1) 51 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 52 mockStorageClient.EXPECT().GetBucketAttrs("scratchbucket").Return(&storage.BucketAttrs{Location: "us-west2"}, nil).Times(1) 53 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 54 err := NewPopulator( 55 mockNetworkResolver, 56 mockMetadataGce, 57 mockStorageClient, 58 mockResourceLocationRetriever, 59 mockScratchBucketCreator, 60 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 61 62 assert.Contains(t, err.Error(), "zone not found") 63 } 64 65 func TestPopulator_PropagatesErrorFromNetworkResolver(t *testing.T) { 66 project := "a_project" 67 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 68 zone := "us-west2-a" 69 region := "" 70 file := "gs://a_bucket/a_file" 71 storageLocation := "US" 72 network := "original-network" 73 subnet := "original-subnet" 74 75 mockCtrl := gomock.NewController(t) 76 defer mockCtrl.Finish() 77 78 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 79 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 80 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 81 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 82 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 83 mockStorageClient.EXPECT().GetBucketAttrs("scratchbucket").Return(&storage.BucketAttrs{Location: "us-west2"}, nil).Times(1) 84 mockNetworkResolver := mocks.NewMockNetworkResolver(mockCtrl) 85 mockNetworkResolver.EXPECT().ResolveAndValidateNetworkAndSubnet("original-network", "original-subnet", "us-west2", "a_project").Return("", "", daisy.Errf("network cannot be found")) 86 err := NewPopulator( 87 mockNetworkResolver, 88 mockMetadataGce, 89 mockStorageClient, 90 mockResourceLocationRetriever, 91 mockScratchBucketCreator, 92 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 93 94 assert.Contains(t, err.Error(), "network cannot be found") 95 } 96 97 func TestPopulator_UsesReturnValuesFromNetworkResolver(t *testing.T) { 98 project := "a_project" 99 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 100 zone := "us-west2-a" 101 region := "" 102 file := "gs://a_bucket/a_file" 103 storageLocation := "US" 104 network := "original-network" 105 subnet := "original-subnet" 106 107 mockCtrl := gomock.NewController(t) 108 defer mockCtrl.Finish() 109 110 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 111 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 112 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 113 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 114 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 115 mockStorageClient.EXPECT().GetBucketAttrs("scratchbucket").Return(&storage.BucketAttrs{Location: "us-west2"}, nil).Times(1) 116 mockNetworkResolver := mocks.NewMockNetworkResolver(mockCtrl) 117 mockNetworkResolver.EXPECT().ResolveAndValidateNetworkAndSubnet( 118 "original-network", "original-subnet", "us-west2", "a_project").Return("fixed-network", "fixed-subnet", nil) 119 err := NewPopulator( 120 mockNetworkResolver, 121 mockMetadataGce, 122 mockStorageClient, 123 mockResourceLocationRetriever, 124 mockScratchBucketCreator, 125 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 126 assert.NoError(t, err) 127 assert.Equal(t, "fixed-network", network) 128 assert.Equal(t, "fixed-subnet", subnet) 129 } 130 131 func TestPopulator_PopulateMissingParametersReturnsErrorWhenProjectNotProvidedAndNotRunningOnGCE(t *testing.T) { 132 project := "" 133 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 134 zone := "" 135 region := "" 136 file := "gs://a_bucket/a_file" 137 storageLocation := "" 138 network := "original-network" 139 subnet := "original-subnet" 140 141 mockCtrl := gomock.NewController(t) 142 defer mockCtrl.Finish() 143 144 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 145 mockMetadataGce.EXPECT().OnGCE().Return(false) 146 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 147 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 148 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 149 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 150 err := NewPopulator( 151 mockNetworkResolver, 152 mockMetadataGce, 153 mockStorageClient, 154 mockResourceLocationRetriever, 155 mockScratchBucketCreator, 156 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 157 158 assert.Contains(t, err.Error(), "project cannot be determined because build is not running on GCE") 159 } 160 161 func TestPopulator_PopulateMissingParametersReturnsErrorWhenProjectNotProvidedAndGCEProjectIdEmpty(t *testing.T) { 162 project := "" 163 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 164 zone := "" 165 region := "" 166 file := "gs://a_bucket/a_file" 167 storageLocation := "" 168 network := "original-network" 169 subnet := "original-subnet" 170 171 mockCtrl := gomock.NewController(t) 172 defer mockCtrl.Finish() 173 174 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 175 mockMetadataGce.EXPECT().OnGCE().Return(true) 176 mockMetadataGce.EXPECT().ProjectID().Return("", nil) 177 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 178 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 179 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 180 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 181 err := NewPopulator( 182 mockNetworkResolver, 183 mockMetadataGce, 184 mockStorageClient, 185 mockResourceLocationRetriever, 186 mockScratchBucketCreator, 187 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 188 189 assert.Contains(t, err.Error(), "project cannot be determined") 190 } 191 192 func TestPopulator_PopulateMissingParametersReturnsErrorWhenProjectNotProvidedAndMetadataReturnsError(t *testing.T) { 193 project := "" 194 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 195 zone := "" 196 region := "" 197 file := "gs://a_bucket/a_file" 198 storageLocation := "" 199 network := "original-network" 200 subnet := "original-subnet" 201 202 mockCtrl := gomock.NewController(t) 203 defer mockCtrl.Finish() 204 205 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 206 mockMetadataGce.EXPECT().OnGCE().Return(true) 207 mockMetadataGce.EXPECT().ProjectID().Return("pr", daisy.Errf("Err")) 208 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 209 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 210 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 211 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 212 err := NewPopulator( 213 mockNetworkResolver, 214 mockMetadataGce, 215 mockStorageClient, 216 mockResourceLocationRetriever, 217 mockScratchBucketCreator, 218 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 219 220 assert.Contains(t, err.Error(), "project cannot be determined") 221 } 222 223 func TestPopulator_PopulateMissingParametersReturnsErrorWhenScratchBucketCreationError(t *testing.T) { 224 project := "a_project" 225 scratchBucketGcsPath := "" 226 zone := "" 227 region := "" 228 file := "gs://a_bucket/a_file" 229 storageLocation := "" 230 network := "original-network" 231 subnet := "original-subnet" 232 233 mockCtrl := gomock.NewController(t) 234 defer mockCtrl.Finish() 235 236 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 237 mockMetadataGce.EXPECT().OnGCE().Return(false) 238 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 239 mockScratchBucketCreator.EXPECT().CreateScratchBucket(file, project, zone).Return("", "", daisy.Errf("err")) 240 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 241 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 242 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 243 err := NewPopulator( 244 mockNetworkResolver, 245 mockMetadataGce, 246 mockStorageClient, 247 mockResourceLocationRetriever, 248 mockScratchBucketCreator, 249 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 250 251 assert.Contains(t, err.Error(), "failed to create scratch bucket") 252 } 253 254 func TestPopulator_PopulateMissingParametersReturnsErrorWhenScratchBucketInvalidFormat(t *testing.T) { 255 project := "a_project" 256 scratchBucketGcsPath := "NOT_GCS_PATH" 257 zone := "" 258 region := "" 259 file := "gs://a_bucket/a_file" 260 storageLocation := "" 261 network := "original-network" 262 subnet := "original-subnet" 263 264 mockCtrl := gomock.NewController(t) 265 defer mockCtrl.Finish() 266 267 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 268 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 269 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 270 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 271 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 272 err := NewPopulator( 273 mockNetworkResolver, 274 mockMetadataGce, 275 mockStorageClient, 276 mockResourceLocationRetriever, 277 mockScratchBucketCreator, 278 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 279 280 assert.Contains(t, err.Error(), "invalid scratch bucket") 281 } 282 283 func TestPopulator_PopulateMissingParametersReturnsErrorWhenPopulateRegionFails(t *testing.T) { 284 project := "a_project" 285 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 286 zone := "NOT_ZONE" 287 region := "NOT_REGION" 288 file := "gs://a_bucket/a_file" 289 storageLocation := "US" 290 network := "original-network" 291 subnet := "original-subnet" 292 293 mockCtrl := gomock.NewController(t) 294 defer mockCtrl.Finish() 295 296 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 297 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 298 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 299 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 300 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 301 mockStorageClient.EXPECT().GetBucketAttrs("scratchbucket").Return(&storage.BucketAttrs{Location: region}, nil) 302 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 303 err := NewPopulator( 304 mockNetworkResolver, 305 mockMetadataGce, 306 mockStorageClient, 307 mockResourceLocationRetriever, 308 mockScratchBucketCreator, 309 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 310 311 assert.Contains(t, err.Error(), "NOT_ZONE is not a valid zone") 312 } 313 314 func TestPopulator_PopulateMissingParametersDoesNotChangeProvidedScratchBucketAndUsesItsRegion(t *testing.T) { 315 project := "a_project" 316 zone := "" 317 region := "" 318 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 319 storageLocation := "US" 320 network := "original-network" 321 subnet := "original-subnet" 322 323 file := "gs://sourcebucket/sourcefile" 324 expectedBucketName := "scratchbucket" 325 expectedRegion := "europe-north1" 326 expectedZone := "europe-north1-b" 327 328 mockCtrl := gomock.NewController(t) 329 defer mockCtrl.Finish() 330 331 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 332 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 333 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 334 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 335 mockResourceLocationRetriever.EXPECT().GetZone(expectedRegion, project).Return(expectedZone, nil).Times(1) 336 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 337 mockStorageClient.EXPECT().GetBucketAttrs(expectedBucketName).Return(&storage.BucketAttrs{Location: expectedRegion}, nil) 338 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 339 err := NewPopulator( 340 mockNetworkResolver, 341 mockMetadataGce, 342 mockStorageClient, 343 mockResourceLocationRetriever, 344 mockScratchBucketCreator, 345 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 346 347 assert.Nil(t, err) 348 assert.Equal(t, "a_project", project) 349 assert.Equal(t, "europe-north1-b", zone) 350 assert.Equal(t, "europe-north1", region) 351 assert.Equal(t, "gs://scratchbucket/scratchpath", scratchBucketGcsPath) 352 } 353 354 func TestPopulator_DeleteResources_WhenScratchBucketInAnotherProject(t *testing.T) { 355 for _, tt := range []struct { 356 caseName string 357 client string 358 deleteResult error 359 deleteExpected bool 360 expectedError string 361 expectedAnonymizedError string 362 scratchBucketGCSPath string 363 fileGCSPath string 364 }{ 365 { 366 caseName: "In scratch - gcloud - Successful deletion", 367 client: "gcloud", 368 deleteResult: nil, 369 deleteExpected: true, 370 expectedError: "Scratch bucket \"scratchbucket\" is not in project \"a_project\". " + 371 "Deleted \"gs://scratchbucket/sourcefile\"", 372 expectedAnonymizedError: "Scratch bucket %q is not in project %q. Deleted %q", 373 scratchBucketGCSPath: "gs://scratchbucket/scratchpath", 374 fileGCSPath: "gs://scratchbucket/sourcefile", 375 }, 376 { 377 caseName: "In scratch - gcloud - Failed deletion", 378 client: "gcloud", 379 deleteResult: errors.New("Failed to delete path"), 380 deleteExpected: true, 381 expectedError: "Scratch bucket \"scratchbucket\" is not in project \"a_project\". Failed to delete " + 382 "\"gs://scratchbucket/sourcefile\": Failed to delete path. " + 383 "Check with the owner of gs://\"scratchbucket\" for more information", 384 expectedAnonymizedError: "Scratch bucket %q is not in project %q. Failed to delete %q: %v. " + 385 "Check with the owner of gs://%q for more information", 386 scratchBucketGCSPath: "gs://scratchbucket/scratchpath", 387 fileGCSPath: "gs://scratchbucket/sourcefile", 388 }, 389 { 390 caseName: "In scratch - not gcloud - don't delete", 391 client: "api", 392 expectedError: "Scratch bucket \"scratchbucket\" is not in project \"a_project\"", 393 expectedAnonymizedError: "Scratch bucket %q is not in project %q", 394 scratchBucketGCSPath: "gs://scratchbucket/scratchpath", 395 fileGCSPath: "gs://scratchbucket/sourcefile", 396 }, 397 { 398 caseName: "Not in scratch - Don't delete", 399 client: "gcloud", 400 expectedError: "Scratch bucket \"scratchbucket\" is not in project \"a_project\"", 401 expectedAnonymizedError: "Scratch bucket %q is not in project %q", 402 scratchBucketGCSPath: "gs://scratchbucket/scratchpath", 403 fileGCSPath: "gs://source-images/sourcefile", 404 }, 405 { 406 caseName: "GCS Image - Don't delete", 407 client: "gcloud", 408 expectedError: "Scratch bucket \"scratchbucket\" is not in project \"a_project\"", 409 expectedAnonymizedError: "Scratch bucket %q is not in project %q", 410 scratchBucketGCSPath: "gs://scratchbucket/scratchpath", 411 fileGCSPath: "", 412 }, 413 } { 414 t.Run(tt.caseName, func(t *testing.T) { 415 project := "a_project" 416 zone := "" 417 region := "" 418 scratchBucketGcsPath := tt.scratchBucketGCSPath 419 storageLocation := "US" 420 file := tt.fileGCSPath 421 network := "original-network" 422 subnet := "original-subnet" 423 424 mockCtrl := gomock.NewController(t) 425 defer mockCtrl.Finish() 426 427 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 428 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 429 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(false) 430 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 431 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 432 if tt.deleteExpected { 433 mockStorageClient.EXPECT().DeleteObject(file).Return(tt.deleteResult) 434 } 435 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 436 err := NewPopulator( 437 mockNetworkResolver, 438 mockMetadataGce, 439 mockStorageClient, 440 mockResourceLocationRetriever, 441 mockScratchBucketCreator, 442 ).PopulateMissingParameters(&project, tt.client, &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 443 444 realError := err.(daisy.DError) 445 assert.EqualError(t, realError, tt.expectedError) 446 assert.Equal(t, strings.Join(realError.AnonymizedErrs(), ""), tt.expectedAnonymizedError) 447 }) 448 } 449 } 450 451 func TestPopulator_PopulateMissingParametersCreatesScratchBucketIfNotProvided(t *testing.T) { 452 project := "a_project" 453 zone := "" 454 region := "" 455 scratchBucketGcsPath := "" 456 storageLocation := "US" 457 network := "original-network" 458 subnet := "original-subnet" 459 460 file := "gs://sourcebucket/sourcefile" 461 expectedBucketName := "new_scratch_bucket" 462 expectedRegion := "europe-north1" 463 expectedZone := "europe-north1-c" 464 465 mockCtrl := gomock.NewController(t) 466 defer mockCtrl.Finish() 467 468 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 469 mockMetadataGce.EXPECT().OnGCE().Return(false) 470 471 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 472 mockScratchBucketCreator.EXPECT(). 473 CreateScratchBucket(file, project, zone). 474 Return(expectedBucketName, expectedRegion, nil). 475 Times(1) 476 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 477 mockResourceLocationRetriever.EXPECT().GetZone(expectedRegion, project).Return(expectedZone, nil).Times(1) 478 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 479 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 480 err := NewPopulator( 481 mockNetworkResolver, 482 mockMetadataGce, 483 mockStorageClient, 484 mockResourceLocationRetriever, 485 mockScratchBucketCreator, 486 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 487 488 assert.Nil(t, err) 489 assert.Equal(t, "a_project", project) 490 assert.Equal(t, expectedZone, zone) 491 assert.Equal(t, expectedRegion, region) 492 assert.Equal(t, fmt.Sprintf("gs://%v/", expectedBucketName), scratchBucketGcsPath) 493 } 494 495 func TestPopulator_PopulateMissingParametersCreatesScratchBucketIfNotProvidedOnGCE(t *testing.T) { 496 project := "a_project" 497 zone := "" 498 region := "" 499 scratchBucketGcsPath := "" 500 storageLocation := "US" 501 network := "original-network" 502 subnet := "original-subnet" 503 504 file := "gs://sourcebucket/sourcefile" 505 expectedBucketName := "new_scratch_bucket" 506 expectedRegion := "europe-north1" 507 expectedZone := "europe-north1-c" 508 509 mockCtrl := gomock.NewController(t) 510 defer mockCtrl.Finish() 511 512 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 513 mockMetadataGce.EXPECT().OnGCE().Return(true) 514 mockMetadataGce.EXPECT().Zone().Return(expectedZone, nil) 515 516 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 517 mockScratchBucketCreator.EXPECT(). 518 CreateScratchBucket(file, project, expectedZone). 519 Return(expectedBucketName, expectedRegion, nil). 520 Times(1) 521 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 522 mockResourceLocationRetriever.EXPECT().GetZone(expectedRegion, project).Return(expectedZone, nil).Times(1) 523 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 524 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 525 err := NewPopulator( 526 mockNetworkResolver, 527 mockMetadataGce, 528 mockStorageClient, 529 mockResourceLocationRetriever, 530 mockScratchBucketCreator, 531 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 532 533 assert.Nil(t, err) 534 assert.Equal(t, "a_project", project) 535 assert.Equal(t, expectedZone, zone) 536 assert.Equal(t, expectedRegion, region) 537 assert.Equal(t, fmt.Sprintf("gs://%v/", expectedBucketName), scratchBucketGcsPath) 538 } 539 540 func TestPopulator_PopulateMissingParametersPopulatesStorageLocationWithScratchBucketLocation(t *testing.T) { 541 project := "a_project" 542 scratchBucketGcsPath := "gs://scratchbucket/scratchpath" 543 zone := "us-central1-b" 544 region := "us-central1" 545 file := "gs://a_bucket/a_file" 546 storageLocation := "" 547 network := "original-network" 548 subnet := "original-subnet" 549 550 mockCtrl := gomock.NewController(t) 551 defer mockCtrl.Finish() 552 553 mockMetadataGce := mocks.NewMockMetadataGCEInterface(mockCtrl) 554 mockScratchBucketCreator := mocks.NewMockScratchBucketCreatorInterface(mockCtrl) 555 mockScratchBucketCreator.EXPECT().IsBucketInProject(project, "scratchbucket").Return(true) 556 mockResourceLocationRetriever := mocks.NewMockResourceLocationRetrieverInterface(mockCtrl) 557 mockStorageClient := mocks.NewMockStorageClientInterface(mockCtrl) 558 mockStorageClient.EXPECT().GetBucketAttrs("scratchbucket").Return(&storage.BucketAttrs{Location: region}, nil) 559 mockResourceLocationRetriever.EXPECT().GetLargestStorageLocation(region).Return("US") 560 mockNetworkResolver := newNoOpNetworkResolver(mockCtrl) 561 err := NewPopulator( 562 mockNetworkResolver, 563 mockMetadataGce, 564 mockStorageClient, 565 mockResourceLocationRetriever, 566 mockScratchBucketCreator, 567 ).PopulateMissingParameters(&project, "gcloud", &zone, ®ion, &scratchBucketGcsPath, file, &storageLocation, &network, &subnet) 568 569 assert.Nil(t, err) 570 assert.Equal(t, "US", storageLocation) 571 } 572 573 func newNoOpNetworkResolver(ctrl *gomock.Controller) NetworkResolver { 574 m := mocks.NewMockNetworkResolver(ctrl) 575 m.EXPECT().ResolveAndValidateNetworkAndSubnet(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 576 return m 577 }