diff --git a/internal/registry/mock_service.go b/internal/registry/mock_service.go index 667ad33bcd2..0980260ac95 100644 --- a/internal/registry/mock_service.go +++ b/internal/registry/mock_service.go @@ -12,10 +12,14 @@ import ( "google.golang.org/grpc/status" ) +//MockPackerClientService represents a basic mock of the Cloud Packer Service. +//Upon calling a service method a boolean is set to true to indicate that a method has been called. +//To skip the setting of these booleans set TrackCalledServiceMethods to false; defaults to true in NewMockPackerClientService(). type MockPackerClientService struct { CreateBucketCalled, UpdateBucketCalled, BucketAlreadyExist bool CreateIterationCalled, GetIterationCalled, IterationAlreadyExist, IterationCompleted bool CreateBuildCalled, UpdateBuildCalled, ListBuildsCalled, BuildAlreadyDone bool + TrackCalledServiceMethods bool // Mock Creates CreateBucketResp *models.HashicorpCloudPackerCreateBucketResponse @@ -31,41 +35,21 @@ type MockPackerClientService struct { packerSvc.ClientService } +//NewMockPackerClientService returns a basic mock of the Cloud Packer Service. +//Upon calling a service method a boolean is set to true to indicate that a method has been called. +//To skip the setting of these booleans set TrackCalledServiceMethods to false. By default it is true. func NewMockPackerClientService() *MockPackerClientService { m := MockPackerClientService{ - ExistingBuilds: make([]string, 0), - } - - m.CreateBucketResp = &models.HashicorpCloudPackerCreateBucketResponse{ - Bucket: &models.HashicorpCloudPackerBucket{ - ID: "bucket-id", - }, - } - - m.CreateIterationResp = &models.HashicorpCloudPackerCreateIterationResponse{ - Iteration: &models.HashicorpCloudPackerIteration{ - ID: "iteration-id", - }, - } - - m.CreateBuildResp = &models.HashicorpCloudPackerCreateBuildResponse{ - Build: &models.HashicorpCloudPackerBuild{ - PackerRunUUID: "test-uuid", - Status: models.HashicorpCloudPackerBuildStatusUNSET, - }, - } - - m.GetIterationResp = &models.HashicorpCloudPackerGetIterationResponse{ - Iteration: &models.HashicorpCloudPackerIteration{ - ID: "iteration-id", - Builds: make([]*models.HashicorpCloudPackerBuild, 0), - }, + ExistingBuilds: make([]string, 0), + ExistingBuildLabels: make(map[string]string), + TrackCalledServiceMethods: true, } return &m } func (svc *MockPackerClientService) PackerServiceCreateBucket(params *packerSvc.PackerServiceCreateBucketParams, _ runtime.ClientAuthInfoWriter) (*packerSvc.PackerServiceCreateBucketOK, error) { + if svc.BucketAlreadyExist { return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Code:%d %s", codes.AlreadyExists, codes.AlreadyExists.String())) } @@ -77,19 +61,27 @@ func (svc *MockPackerClientService) PackerServiceCreateBucket(params *packerSvc. return nil, errors.New("No bucket slug was passed in") } - svc.CreateBucketCalled = true - // This is set in NewMockPackerClientService() - svc.CreateBucketResp.Bucket.Slug = params.Body.BucketSlug + if svc.TrackCalledServiceMethods { + svc.CreateBucketCalled = true + } + payload := &models.HashicorpCloudPackerCreateBucketResponse{ + Bucket: &models.HashicorpCloudPackerBucket{ + ID: "bucket-id", + }, + } + payload.Bucket.Slug = params.Body.BucketSlug ok := &packerSvc.PackerServiceCreateBucketOK{ - Payload: svc.CreateBucketResp, + Payload: payload, } return ok, nil } func (svc *MockPackerClientService) PackerServiceUpdateBucket(params *packerSvc.PackerServiceUpdateBucketParams, _ runtime.ClientAuthInfoWriter) (*packerSvc.PackerServiceUpdateBucketOK, error) { - svc.UpdateBucketCalled = true + if svc.TrackCalledServiceMethods { + svc.UpdateBucketCalled = true + } return packerSvc.NewPackerServiceUpdateBucketOK(), nil } @@ -107,12 +99,20 @@ func (svc *MockPackerClientService) PackerServiceCreateIteration(params *packerS return nil, errors.New("No valid Fingerprint was passed in") } - svc.CreateIterationCalled = true - svc.CreateIterationResp.Iteration.BucketSlug = params.Body.BucketSlug - svc.CreateIterationResp.Iteration.Fingerprint = params.Body.Fingerprint + if svc.TrackCalledServiceMethods { + svc.CreateIterationCalled = true + } + payload := &models.HashicorpCloudPackerCreateIterationResponse{ + Iteration: &models.HashicorpCloudPackerIteration{ + ID: "iteration-id", + }, + } + + payload.Iteration.BucketSlug = params.Body.BucketSlug + payload.Iteration.Fingerprint = params.Body.Fingerprint ok := &packerSvc.PackerServiceCreateIterationOK{ - Payload: svc.CreateIterationResp, + Payload: payload, } return ok, nil @@ -131,11 +131,21 @@ func (svc *MockPackerClientService) PackerServiceGetIteration(params *packerSvc. return nil, errors.New("No valid Fingerprint was passed in") } - svc.GetIterationCalled = true + if svc.TrackCalledServiceMethods { + svc.GetIterationCalled = true + } - // + payload := &models.HashicorpCloudPackerGetIterationResponse{ + Iteration: &models.HashicorpCloudPackerIteration{ + ID: "iteration-id", + Builds: make([]*models.HashicorpCloudPackerBuild, 0), + }, + } + + payload.Iteration.BucketSlug = params.BucketSlug + payload.Iteration.Fingerprint = *params.Fingerprint ok := &packerSvc.PackerServiceGetIterationOK{ - Payload: svc.GetIterationResp, + Payload: payload, } if svc.IterationCompleted { @@ -168,13 +178,22 @@ func (svc *MockPackerClientService) PackerServiceCreateBuild(params *packerSvc.P return nil, errors.New("No build componentType was passed in") } - svc.CreateBuildCalled = true + if svc.TrackCalledServiceMethods { + svc.CreateBuildCalled = true + } + + payload := &models.HashicorpCloudPackerCreateBuildResponse{ + Build: &models.HashicorpCloudPackerBuild{ + PackerRunUUID: "test-uuid", + Status: models.HashicorpCloudPackerBuildStatusUNSET, + }, + } - svc.CreateBuildResp.Build.ComponentType = params.Body.Build.ComponentType - svc.CreateBuildResp.Build.IterationID = params.IterationID + payload.Build.ComponentType = params.Body.Build.ComponentType + payload.Build.IterationID = params.IterationID ok := packerSvc.NewPackerServiceCreateBuildOK() - ok.Payload = svc.CreateBuildResp + ok.Payload = payload return ok, nil } @@ -192,7 +211,10 @@ func (svc *MockPackerClientService) PackerServiceUpdateBuild(params *packerSvc.P return nil, errors.New("No build status was passed in") } - svc.UpdateBuildCalled = true + if svc.TrackCalledServiceMethods { + svc.UpdateBuildCalled = true + } + ok := packerSvc.NewPackerServiceUpdateBuildOK() ok.Payload = &models.HashicorpCloudPackerUpdateBuildResponse{ Build: &models.HashicorpCloudPackerBuild{ diff --git a/internal/registry/types.bucket.go b/internal/registry/types.bucket.go index 6d9c4d3b49f..95cb421ae30 100644 --- a/internal/registry/types.bucket.go +++ b/internal/registry/types.bucket.go @@ -352,6 +352,7 @@ func (b *Bucket) PopulateIteration(ctx context.Context) error { var errs *multierror.Error var wg sync.WaitGroup + var mu sync.Mutex for _, buildName := range toCreate { wg.Add(1) go func(name string) { @@ -365,10 +366,12 @@ func (b *Bucket) PopulateIteration(ctx context.Context) error { return } + mu.Lock() errs = multierror.Append(errs, err) + mu.Unlock() }(buildName) - wg.Wait() } + wg.Wait() return errs.ErrorOrNil() } diff --git a/internal/registry/types.bucket_test.go b/internal/registry/types.bucket_test.go index d4429535cfc..6b49c003d23 100644 --- a/internal/registry/types.bucket_test.go +++ b/internal/registry/types.bucket_test.go @@ -8,7 +8,7 @@ import ( "github.com/google/go-cmp/cmp" ) -func createInitialTestBucket(t testing.TB) (*Bucket, *MockPackerClientService) { +func createInitialTestBucket(t testing.TB) *Bucket { oldEnv := os.Getenv("HCP_PACKER_BUILD_FINGERPRINT") os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "no-fingerprint-here") defer func() { @@ -22,12 +22,13 @@ func createInitialTestBucket(t testing.TB) (*Bucket, *MockPackerClientService) { } mockService := NewMockPackerClientService() + mockService.TrackCalledServiceMethods = false bucket.Slug = "TestBucket" bucket.client = &Client{ Packer: mockService, } - return bucket, mockService + return bucket } func checkError(t testing.TB, err error) { @@ -41,7 +42,7 @@ func checkError(t testing.TB, err error) { } func TestBucket_CreateInitialBuildForIteration(t *testing.T) { - bucket, _ := createInitialTestBucket(t) + bucket := createInitialTestBucket(t) componentName := "happycloud.image" bucket.RegisterBuildForComponent(componentName) @@ -118,7 +119,7 @@ func TestBucket_UpdateLabelsForBuild(t *testing.T) { for _, tt := range tc { tt := tt t.Run(tt.desc, func(t *testing.T) { - bucket, mockService := createInitialTestBucket(t) + bucket := createInitialTestBucket(t) componentName := tt.buildName bucket.RegisterBuildForComponent(componentName) @@ -127,13 +128,9 @@ func TestBucket_UpdateLabelsForBuild(t *testing.T) { bucket.BuildLabels[k] = v } - err := bucket.PopulateIteration(context.TODO()) + err := bucket.CreateInitialBuildForIteration(context.TODO(), componentName) checkError(t, err) - if !mockService.CreateBuildCalled { - t.Errorf("expected an initial build for %s to be created by calling CreateBuild", componentName) - } - // Assert that the build is stored on the iteration build, err := bucket.Iteration.Build(componentName) if err != nil { @@ -161,7 +158,7 @@ func TestBucket_UpdateLabelsForBuild(t *testing.T) { } func TestBucket_UpdateLabelsForBuild_withMultipleBuilds(t *testing.T) { - bucket, _ := createInitialTestBucket(t) + bucket := createInitialTestBucket(t) firstComponent := "happycloud.image" bucket.RegisterBuildForComponent(firstComponent)