Update CreateIntialBuildForIteration to initialize each build its own map (#11574)

* Rename mock bucket test file

* Add failing tests for reproducing #11573

```
=== RUN   TestBucket_CreateInitialBuildForIteration
2022/02/16 16:22:21 [TRACE] creating initial build for component happycloud.image
--- PASS: TestBucket_CreateInitialBuildForIteration (0.00s)
=== RUN   TestBucket_UpdateLabelsForBuild
2022/02/16 16:22:21 [TRACE] creating initial build for component happycloud.image
    types.bucket_test.go:87: expected the initial build to have an additional build label but thee is no diff: ""
--- FAIL: TestBucket_UpdateLabelsForBuild (0.00s)
=== RUN   TestBucket_UpdateLabelsForBuild_withMultipleBuilds
2022/02/16 16:22:21 [TRACE] creating initial build for component happycloud.image
2022/02/16 16:22:21 [TRACE] creating initial build for component happycloud.image2
    types.bucket_test.go:125: Comparing component build labels: map[based_off:alpine source_image:another-happycloud-image version:1.7.0]
         against global build labels: map[based_off:alpine source_image:another-happycloud-image version:1.7.0]
    types.bucket_test.go:128: expected the initial build to have an additional build label but they are equal
    types.bucket_test.go:125: Comparing component build labels: map[based_off:alpine source_image:another-happycloud-image version:1.7.0]
         against global build labels: map[based_off:alpine source_image:another-happycloud-image version:1.7.0]
    types.bucket_test.go:128: expected the initial build to have an additional build label but they are equal
--- FAIL: TestBucket_UpdateLabelsForBuild_withMultipleBuilds (0.00s)
FAIL
FAIL    github.com/hashicorp/packer/internal/registry   0.646s

```

* Update CreateIntialBuildForIteration to initialize each build with a new map

Previously upon creating the initial build the same map, which was
initialized for the build_labels argument was being shared across all
build images. This was causing an issue with labels being backed by the
same map for all builds. This change ensures that all builds get their
own map with any global build labels copied over during the initial creation.

Closes #11573

Passing tests with changes on branch
```
RUN   TestBucket_CreateInitialBuildForIteration
2022/02/16 16:37:40 [TRACE] creating initial build for component happycloud.image
--- PASS: TestBucket_CreateInitialBuildForIteration (0.00s)
=== RUN   TestBucket_UpdateLabelsForBuild
2022/02/16 16:37:40 [TRACE] creating initial build for component happycloud.image
--- PASS: TestBucket_UpdateLabelsForBuild (0.00s)
=== RUN   TestBucket_UpdateLabelsForBuild_withMultipleBuilds
2022/02/16 16:37:40 [TRACE] creating initial build for component happycloud.image
2022/02/16 16:37:40 [TRACE] creating initial build for component happycloud.image2
    types.bucket_test.go:125: Comparing component build labels: map[based_off:alpine source_image:another-happycloud-image version:1.7.0]
         against global build labels: map[based_off:alpine version:1.7.0]
    types.bucket_test.go:125: Comparing component build labels: map[based_off:alpine source_image:the-original-happycloud-image version:1.7.0]
         against global build labels: map[based_off:alpine version:1.7.0]
--- PASS: TestBucket_UpdateLabelsForBuild_withMultipleBuilds (0.00s)

```

* Handle errors from bucket methods

* Update test cases

Initialize maps for bucket when calling NewBucketWithIteration
pull/11586/head
Wilken Rivera 4 years ago committed by GitHub
parent df5699c10d
commit 119a825296
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -29,7 +29,10 @@ type Bucket struct {
// NewBucketWithIteration initializes a simple Bucket that can be used publishing Packer build
// images to the HCP Packer registry.
func NewBucketWithIteration(opts IterationOptions) (*Bucket, error) {
b := Bucket{}
b := Bucket{
BucketLabels: make(map[string]string),
BuildLabels: make(map[string]string),
}
i, err := NewIteration(opts)
if err != nil {
@ -114,21 +117,21 @@ func (b *Bucket) CreateInitialBuildForIteration(ctx context.Context, componentTy
}
id := resp.Payload.Build.ID
if b.BuildLabels == nil {
b.BuildLabels = make(map[string]string)
}
build := &Build{
build := Build{
ID: id,
ComponentType: componentType,
RunUUID: b.Iteration.RunUUID,
Status: status,
Labels: b.BuildLabels,
Labels: make(map[string]string),
Images: make(map[string]registryimage.Image),
}
for k, v := range b.BuildLabels {
build.Labels[k] = v
}
log.Println("[TRACE] creating initial build for component", componentType)
b.Iteration.builds.Store(componentType, build)
b.Iteration.builds.Store(componentType, &build)
return nil
}

@ -0,0 +1,385 @@
package registry
import (
"context"
"os"
"testing"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/preview/2021-04-30/models"
)
func TestInitialize_NewBucketNewIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBucketCalled {
t.Errorf("expected a call to CreateBucket but it didn't happen")
}
if !mockService.CreateIterationCalled {
t.Errorf("expected a call to CreateIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("Didn't expect a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBuildCalled {
t.Errorf("Expected a call to CreateBuild but it didn't happen")
}
if _, ok := b.Iteration.builds.Load("happycloud.image"); !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
}
func TestInitialize_ExistingBucketNewIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.UpdateBucketCalled {
t.Errorf("expected call to UpdateBucket but it didn't happen")
}
if !mockService.CreateIterationCalled {
t.Errorf("expected a call to CreateIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("Didn't expect a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBuildCalled {
t.Errorf("Expected a call to CreateBuild but it didn't happen")
}
if _, ok := b.Iteration.builds.Load("happycloud.image"); !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
}
func TestInitialize_ExistingBucketExistingIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if mockService.CreateBucketCalled {
t.Errorf("unexpected call to CreateBucket")
}
if !mockService.UpdateBucketCalled {
t.Errorf("expected call to UpdateBucket but it didn't happen")
}
if mockService.CreateIterationCalled {
t.Errorf("unexpected a call to CreateIteration")
}
if !mockService.GetIterationCalled {
t.Errorf("expected a call to GetIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("unexpected a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
existingBuild, ok := loadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
}
func TestInitialize_ExistingBucketCompleteIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
mockService.IterationCompleted = true
mockService.BuildAlreadyDone = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err == nil {
t.Errorf("unexpected failure: %v", err)
}
if mockService.CreateIterationCalled {
t.Errorf("unexpected call to CreateIteration")
}
if !mockService.GetIterationCalled {
t.Errorf("expected a call to GetIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("unexpected call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to be returned but it wasn't")
}
}
func TestUpdateBuildStatus(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
existingBuild, ok := loadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
if err != nil {
t.Errorf("unexpected failure for PublishBuildStatus: %v", err)
}
reloadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
existingBuild, ok = reloadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
t.Errorf("expected the existing build to be in the running state")
}
}
func TestUpdateBuildStatus_DONENoImages(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
existingBuild, ok := loadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
//nolint:errcheck
b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusDONE)
if err == nil {
t.Errorf("expected failure for PublishBuildStatus when setting status to DONE with no images")
}
reloadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
existingBuild, ok = reloadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
t.Errorf("expected the existing build to be in the running state")
}
}
//func (b *Bucket) PublishBuildStatus(ctx context.Context, name string, status models.HashicorpCloudPackerBuildStatus) error {}

@ -5,381 +5,192 @@ import (
"os"
"testing"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/preview/2021-04-30/models"
"github.com/google/go-cmp/cmp"
)
func TestInitialize_NewBucketNewIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
func createInitialBucket(t testing.TB) *Bucket {
oldEnv := os.Getenv("HCP_PACKER_BUILD_FINGERPRINT")
os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "no-fingerprint-here")
defer func() {
os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", oldEnv)
}()
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
t.Helper()
subject, err := NewBucketWithIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBucketCalled {
t.Errorf("expected a call to CreateBucket but it didn't happen")
}
if !mockService.CreateIterationCalled {
t.Errorf("expected a call to CreateIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("Didn't expect a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
t.Fatalf("failed when calling NewBucketWithIteration: %s", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBuildCalled {
t.Errorf("Expected a call to CreateBuild but it didn't happen")
subject.Slug = "TestBucket"
subject.BuildLabels = map[string]string{
"version": "1.7.0",
"based_off": "alpine",
}
if _, ok := b.Iteration.builds.Load("happycloud.image"); !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
subject.client = &Client{
Packer: NewMockPackerClientService(),
}
return subject
}
func TestInitialize_ExistingBucketNewIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.UpdateBucketCalled {
t.Errorf("expected call to UpdateBucket but it didn't happen")
}
if !mockService.CreateIterationCalled {
t.Errorf("expected a call to CreateIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("Didn't expect a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
}
func checkError(t testing.TB, err error) {
t.Helper()
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
if !mockService.CreateBuildCalled {
t.Errorf("Expected a call to CreateBuild but it didn't happen")
}
if _, ok := b.Iteration.builds.Load("happycloud.image"); !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
if err == nil {
return
}
t.Errorf("received an error during testing %s", err)
}
func TestInitialize_ExistingBucketExistingIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
func TestBucket_CreateInitialBuildForIteration(t *testing.T) {
subject := createInitialBucket(t)
if mockService.CreateBucketCalled {
t.Errorf("unexpected call to CreateBucket")
}
componentName := "happycloud.image"
subject.RegisterBuildForComponent(componentName)
err := subject.CreateInitialBuildForIteration(context.TODO(), componentName)
checkError(t, err)
if !mockService.UpdateBucketCalled {
t.Errorf("expected call to UpdateBucket but it didn't happen")
}
if mockService.CreateIterationCalled {
t.Errorf("unexpected a call to CreateIteration")
}
if !mockService.GetIterationCalled {
t.Errorf("expected a call to GetIteration but it didn't happen")
}
if mockService.CreateBuildCalled {
t.Errorf("unexpected a call to CreateBuild")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to created but it didn't")
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
// Assert that a build stored on the iteration
iBuild, ok := subject.Iteration.builds.Load(componentName)
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
existingBuild, ok := loadedBuild.(*Build)
build, ok := iBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
}
func TestInitialize_ExistingBucketCompleteIteration(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
mockService.IterationCompleted = true
mockService.BuildAlreadyDone = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = b.Initialize(context.TODO())
if err == nil {
t.Errorf("unexpected failure: %v", err)
}
if mockService.CreateIterationCalled {
t.Errorf("unexpected call to CreateIteration")
}
if !mockService.GetIterationCalled {
t.Errorf("expected a call to GetIteration but it didn't happen")
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
if mockService.CreateBuildCalled {
t.Errorf("unexpected call to CreateBuild")
if build.ComponentType != componentName {
t.Errorf("expected the initial build to have the defined component type")
}
if b.Iteration.ID != "iteration-id" {
t.Errorf("expected an iteration to be returned but it wasn't")
if diff := cmp.Diff(build.Labels, subject.BuildLabels); diff != "" {
t.Errorf("expected the initial build to have the defined build labels %v", diff)
}
}
func TestUpdateBuildStatus(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
func TestBucket_UpdateLabelsForBuild(t *testing.T) {
tc := []struct {
desc string
components []string
labels map[string]string
labelsCount int
noDiffExpected bool
}{
{
desc: "only global build labels",
components: []string{"happcloud.image"},
labelsCount: 2,
noDiffExpected: true,
},
{
desc: "global build labels and one additional build specific label",
components: []string{"happcloud.image"},
labels: map[string]string{
"source_image": "another-happycloud-image",
},
labelsCount: 3,
noDiffExpected: false,
},
}
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
for _, tt := range tc {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
subject := createInitialBucket(t)
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
for _, componentName := range tt.components {
subject.RegisterBuildForComponent(componentName)
err := subject.CreateInitialBuildForIteration(context.TODO(), componentName)
checkError(t, err)
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = subject.UpdateLabelsForBuild(componentName, tt.labels)
checkError(t, err)
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
// Assert that the build is stored on the iteration
iBuild, ok := subject.Iteration.builds.Load(componentName)
if !ok {
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
existingBuild, ok := loadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
build, ok := iBuild.(*Build)
if !ok {
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
if build.ComponentType != componentName {
t.Errorf("expected the build to have the defined component type")
}
err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
if err != nil {
t.Errorf("unexpected failure for PublishBuildStatus: %v", err)
}
if len(build.Labels) != tt.labelsCount {
t.Errorf("expected the build to have %d build labels but there is only: %d", tt.labelsCount, len(build.Labels))
}
reloadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
diff := cmp.Diff(build.Labels, subject.BuildLabels)
if (diff == "") != tt.noDiffExpected {
t.Errorf("expected the build to have an additional build label but there is no diff: %q", diff)
}
existingBuild, ok = reloadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
t.Errorf("expected the existing build to be in the running state")
}
})
}
}
func TestUpdateBuildStatus_DONENoImages(t *testing.T) {
//nolint:errcheck
os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber")
defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT")
mockService := NewMockPackerClientService()
mockService.BucketAlreadyExist = true
mockService.IterationAlreadyExist = true
b := &Bucket{
Slug: "TestBucket",
client: &Client{
Packer: mockService,
},
}
func TestBucket_UpdateLabelsForBuild_withMultipleBuilds(t *testing.T) {
subject := createInitialBucket(t)
var err error
b.Iteration, err = NewIteration(IterationOptions{})
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
firstComponent := "happycloud.image"
subject.RegisterBuildForComponent(firstComponent)
err := subject.CreateInitialBuildForIteration(context.TODO(), firstComponent)
checkError(t, err)
b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
err = subject.UpdateLabelsForBuild(firstComponent, map[string]string{
"source_image": "another-happycloud-image",
})
checkError(t, err)
err = b.Initialize(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
err = b.PopulateIteration(context.TODO())
if err != nil {
t.Errorf("unexpected failure: %v", err)
}
secondComponent := "happycloud.image2"
subject.RegisterBuildForComponent(secondComponent)
err = subject.CreateInitialBuildForIteration(context.TODO(), secondComponent)
checkError(t, err)
loadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
}
err = subject.UpdateLabelsForBuild(secondComponent, map[string]string{
"source_image": "the-original-happycloud-image",
"role_name": "no-role-is-a-good-role",
})
checkError(t, err)
existingBuild, ok := loadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
}
var registeredBuilds []*Build
expectedComponents := []string{firstComponent, secondComponent}
for _, componentName := range expectedComponents {
// Assert that a build stored on the iteration
iBuild, ok := subject.Iteration.builds.Load(componentName)
if !ok {
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
t.Errorf("expected the existing build to be in the default state")
}
build, ok := iBuild.(*Build)
if !ok {
t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
}
registeredBuilds = append(registeredBuilds, build)
//nolint:errcheck
b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
if build.ComponentType != componentName {
t.Errorf("expected the initial build to have the defined component type")
}
err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusDONE)
if err == nil {
t.Errorf("expected failure for PublishBuildStatus when setting status to DONE with no images")
if ok := cmp.Equal(build.Labels, subject.BuildLabels); ok {
t.Errorf("expected the build to have an additional build label but they are equal")
}
}
reloadedBuild, ok := b.Iteration.builds.Load("happycloud.image")
if !ok {
t.Errorf("expected a basic build entry to be created but it didn't")
if len(registeredBuilds) != 2 {
t.Errorf("expected the bucket to have 2 registered builds but got %d", len(registeredBuilds))
}
existingBuild, ok = reloadedBuild.(*Build)
if !ok {
t.Errorf("expected the existing build loaded from an existing bucket to be valid")
if ok := cmp.Equal(registeredBuilds[0].Labels, registeredBuilds[1].Labels); ok {
t.Errorf("expected registered builds to have different labels but they are equal")
}
if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
t.Errorf("expected the existing build to be in the running state")
}
}
//func (b *Bucket) PublishBuildStatus(ctx context.Context, name string, status models.HashicorpCloudPackerBuildStatus) error {}

Loading…
Cancel
Save