diff --git a/hcl2template/common_test.go b/hcl2template/common_test.go index 9a9125fae54..619a3e19ab2 100644 --- a/hcl2template/common_test.go +++ b/hcl2template/common_test.go @@ -366,6 +366,9 @@ var cmpOpts = []cmp.Option{ cmpopts.IgnoreFields(packerregistry.Iteration{}, "Fingerprint", // Fingerprint will change everytime ), + cmpopts.IgnoreFields(packerregistry.Bucket{}, + "SourceImagesToParentIterations", // Requires execution of datasource at this time + ), cmpopts.IgnoreFields(VariableAssignment{}, "Expr", // its an interface ), diff --git a/hcl2template/types.build.go b/hcl2template/types.build.go index d317faa765a..5b65b555175 100644 --- a/hcl2template/types.build.go +++ b/hcl2template/types.build.go @@ -253,6 +253,21 @@ func (p *Parser) decodeBuildConfig(block *hcl.Block, cfg *PackerConfig) (*BuildB for _, source := range build.Sources { cfg.bucket.RegisterBuildForComponent(source.String()) } + + // Known HCP Packer Image Datasource, whose id is the SourceImageId for some build. + const hcpDatasourceType string = "hcp-packer-image" + values := ectx.Variables[dataAccessor].AsValueMap() + + dsValues, ok := values[hcpDatasourceType] + if !ok { + return build, diags + } + + for _, value := range dsValues.AsValueMap() { + values := value.AsValueMap() + imgID, itID := values["id"], values["iteration_id"] + cfg.bucket.SourceImagesToParentIterations[imgID.AsString()] = itID.AsString() + } } return build, diags diff --git a/hcl2template/types.build.hcp_packer_registry.go b/hcl2template/types.build.hcp_packer_registry.go index 5f369054424..0dfca96a5c0 100644 --- a/hcl2template/types.build.hcp_packer_registry.go +++ b/hcl2template/types.build.hcp_packer_registry.go @@ -48,7 +48,8 @@ func (p *Parser) decodeHCPRegistry(block *hcl.Block, cfg *PackerConfig) (*HCPPac BuildLabels map[string]string `hcl:"build_labels,optional"` Config hcl.Body `hcl:",remain"` } - diags := gohcl.DecodeBody(body, cfg.EvalContext(LocalContext, nil), &b) + ectx := cfg.EvalContext(BuildContext, nil) + diags := gohcl.DecodeBody(body, ectx, &b) if diags.HasErrors() { return nil, diags } diff --git a/hcl2template/types.build.hcp_packer_registry_test.go b/hcl2template/types.build.hcp_packer_registry_test.go index 967adef5e33..d8aa1425bc1 100644 --- a/hcl2template/types.build.hcp_packer_registry_test.go +++ b/hcl2template/types.build.hcp_packer_registry_test.go @@ -1,6 +1,7 @@ package hcl2template import ( + "os" "path/filepath" "testing" @@ -11,6 +12,9 @@ import ( ) func Test_ParseHCPPackerRegistryBlock(t *testing.T) { + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "hcp-par-test") + defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") + defaultParser := getBasicParser() tests := []parseTest{ diff --git a/internal/registry/service.go b/internal/registry/service.go index 4eb953dc3f7..e10d07faf17 100644 --- a/internal/registry/service.go +++ b/internal/registry/service.go @@ -192,6 +192,7 @@ func (client *Client) UpdateBuild( runUUID, cloudProvider, sourceImageID string, + sourceIterationID string, labels map[string]string, status models.HashicorpCloudPackerBuildStatus, images []*models.HashicorpCloudPackerImageCreateBody, @@ -205,12 +206,13 @@ func (client *Client) UpdateBuild( params.Body = &models.HashicorpCloudPackerUpdateBuildRequest{ BuildID: buildID, Updates: &models.HashicorpCloudPackerBuildUpdates{ - Images: images, - PackerRunUUID: runUUID, - Labels: labels, - Status: status, - CloudProvider: cloudProvider, - SourceImageID: sourceImageID, + Images: images, + PackerRunUUID: runUUID, + Labels: labels, + Status: status, + CloudProvider: cloudProvider, + SourceImageID: sourceImageID, + SourceIterationID: sourceIterationID, }, } diff --git a/internal/registry/types.bucket.go b/internal/registry/types.bucket.go index 1106a7e94f9..34c69a9c9f1 100644 --- a/internal/registry/types.bucket.go +++ b/internal/registry/types.bucket.go @@ -17,21 +17,23 @@ import ( // Bucket represents a single Image bucket on the HCP Packer registry. type Bucket struct { - Slug string - Description string - Destination string - BucketLabels map[string]string - BuildLabels map[string]string - Iteration *Iteration - client *Client + Slug string + Description string + Destination string + BucketLabels map[string]string + BuildLabels map[string]string + SourceImagesToParentIterations map[string]string + Iteration *Iteration + client *Client } // 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{ - BucketLabels: make(map[string]string), - BuildLabels: make(map[string]string), + BucketLabels: make(map[string]string), + BuildLabels: make(map[string]string), + SourceImagesToParentIterations: make(map[string]string), } i, err := NewIteration(opts) @@ -156,6 +158,7 @@ func (b *Bucket) UpdateBuildStatus(ctx context.Context, name string, status mode buildToUpdate.RunUUID, buildToUpdate.CloudProvider, "", + "", buildToUpdate.Labels, status, nil, @@ -192,7 +195,7 @@ func (b *Bucket) markBuildComplete(ctx context.Context, name string) error { return fmt.Errorf("setting a build to DONE with no published images is not currently supported.") } - var providerName, sourceID string + var providerName, sourceID, sourceIterationID string images := make([]*models.HashicorpCloudPackerImageCreateBody, 0, len(buildToUpdate.Images)) for _, image := range buildToUpdate.Images { // These values will always be the same for all images in a single build, @@ -204,6 +207,11 @@ func (b *Bucket) markBuildComplete(ctx context.Context, name string) error { sourceID = image.SourceImageID } + // Check if image is using some other HCP Packer image + if v, ok := b.SourceImagesToParentIterations[image.SourceImageID]; ok { + sourceIterationID = v + } + images = append(images, &models.HashicorpCloudPackerImageCreateBody{ImageID: image.ImageID, Region: image.ProviderRegion}) } @@ -212,6 +220,7 @@ func (b *Bucket) markBuildComplete(ctx context.Context, name string) error { buildToUpdate.RunUUID, buildToUpdate.CloudProvider, sourceID, + sourceIterationID, buildToUpdate.Labels, status, images, diff --git a/internal/registry/types.bucket_service_test.go b/internal/registry/types.bucket_service_test.go index cec08f8ecb0..faf77dc624c 100644 --- a/internal/registry/types.bucket_service_test.go +++ b/internal/registry/types.bucket_service_test.go @@ -10,7 +10,7 @@ import ( func TestInitialize_NewBucketNewIteration(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() @@ -66,7 +66,7 @@ func TestInitialize_NewBucketNewIteration(t *testing.T) { func TestInitialize_ExistingBucketNewIteration(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true @@ -123,7 +123,7 @@ func TestInitialize_ExistingBucketNewIteration(t *testing.T) { func TestInitialize_ExistingBucketExistingIteration(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true @@ -195,7 +195,7 @@ func TestInitialize_ExistingBucketExistingIteration(t *testing.T) { func TestInitialize_ExistingBucketCompleteIteration(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true @@ -243,7 +243,7 @@ func TestInitialize_ExistingBucketCompleteIteration(t *testing.T) { func TestUpdateBuildStatus(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true @@ -300,7 +300,7 @@ func TestUpdateBuildStatus(t *testing.T) { func TestUpdateBuildStatus_DONENoImages(t *testing.T) { //nolint:errcheck - os.Setenv("HCP_PACKER_BUILD_FINGEPRINT", "testnumber") + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "testnumber") defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true diff --git a/internal/registry/types.bucket_test.go b/internal/registry/types.bucket_test.go index f21319c5144..113fb528920 100644 --- a/internal/registry/types.bucket_test.go +++ b/internal/registry/types.bucket_test.go @@ -3,6 +3,7 @@ package registry import ( "context" "os" + "strconv" "testing" "github.com/google/go-cmp/cmp" @@ -278,10 +279,13 @@ func TestBucket_PopulateIteration(t *testing.T) { }, } - for _, tt := range tc { + for i, tt := range tc { tt := tt t.Run(tt.desc, func(t *testing.T) { + os.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "test-run-"+strconv.Itoa(i)) + defer os.Unsetenv("HCP_PACKER_BUILD_FINGERPRINT") + mockService := NewMockPackerClientService() mockService.BucketAlreadyExist = true mockService.IterationAlreadyExist = true