diff --git a/command/build.go b/command/build.go index 787d776bd..c0c43a86f 100644 --- a/command/build.go +++ b/command/build.go @@ -248,6 +248,22 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int defer limitParallel.Release(1) + if ArtifactMetadataPublisher != nil { + err := ArtifactMetadataPublisher.BuildStart(buildCtx, name) + if err != nil { + msg := err.Error() + if strings.Contains(msg, "already done") { + ui.Say(fmt.Sprintf( + "Build %q already done for bucket %q, skipping to prevent drift: %q", + name, + ArtifactMetadataPublisher.Slug, + err)) + return + } + + } + } + log.Printf("Starting build run: %s", name) runArtifacts, err := b.Run(buildCtx, ui) @@ -256,6 +272,19 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int buildDuration := buildEnd.Sub(buildStart) fmtBuildDuration := durafmt.Parse(buildDuration).LimitFirstN(2) + if ArtifactMetadataPublisher != nil { + runArtifacts, err = ArtifactMetadataPublisher.BuildDone( + buildCtx, + name, + runArtifacts, + err, + ) + if err != nil { + ui.Error(fmt.Sprintf("failed to complete HCP build %q: %s", + name, err)) + } + } + if err != nil { ui.Error(fmt.Sprintf("Build '%s' errored after %s: %s", name, fmtBuildDuration, err)) errors.Lock() @@ -280,7 +309,6 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int log.Printf("Parallelization disabled, waiting for build to finish: %s", b.Name()) wg.Wait() } - } // Wait for both the builds to complete and the interrupt handler, diff --git a/command/registry_test.go b/command/registry_test.go index 42348725a..a05ba1d7d 100644 --- a/command/registry_test.go +++ b/command/registry_test.go @@ -47,7 +47,6 @@ var registryCmpOpts = cmp.Options{ file.Builder{}, registry.Bucket{}, registry.Iteration{}, - packer.RegistryBuilder{}, ), } @@ -58,74 +57,20 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/multiple_sources.pkr.hcl", []packersdk.Build{ &packer.CoreBuild{ - BuildName: "bucket-slug", - Type: "file.test", - Prepared: true, - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - BuildLabels: map[string]string{"python_version": "3.0"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - BuildLabels: map[string]string{"python_version": "3.0"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + BuildName: "bucket-slug", + Type: "file.test", + Prepared: true, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, &packer.CoreBuild{ - BuildName: "bucket-slug", - Type: "file.other", - Prepared: true, - Builder: &packer.RegistryBuilder{ - Name: "file.other", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - BuildLabels: map[string]string{"python_version": "3.0"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.other", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - BuildLabels: map[string]string{"python_version": "3.0"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + BuildName: "bucket-slug", + Type: "file.other", + Prepared: true, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, @@ -136,37 +81,12 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/slug.pkr.hcl", []packersdk.Build{ &packer.CoreBuild{ - BuildName: "bucket-slug", - Type: "file.test", - Prepared: true, - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "real-bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "real-bucket-slug", - Description: "Some description\n", - BucketLabels: map[string]string{"foo": "bar"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + BuildName: "bucket-slug", + Type: "file.test", + Prepared: true, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, @@ -177,35 +97,12 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/build-description.pkr.hcl", []packersdk.Build{ &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - BuildName: "bucket-slug", - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some build description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some build description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + Type: "file.test", + Prepared: true, + BuildName: "bucket-slug", + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, @@ -216,34 +113,11 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/override-build-description.pkr.hcl", []packersdk.Build{ &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some override description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some override description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + Type: "file.test", + Prepared: true, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, @@ -254,34 +128,11 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/deprecated_labels.pkr.hcl", []packersdk.Build{ &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - BucketLabels: map[string]string{"foo": "bar"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - BucketLabels: map[string]string{"foo": "bar"}, - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - }, - }, - }, - }, - }, + Type: "file.test", + Prepared: true, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, true, @@ -306,39 +157,12 @@ func TestRegistrySetup(t *testing.T) { "test-fixtures/hcp/hcp_normal.pkr.json", []packersdk.Build{ &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - BuildName: "test-file", - Builder: &packer.RegistryBuilder{ - Name: "file.test", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some build description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - BucketLabels: map[string]string{}, - BuildLabels: map[string]string{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file.test", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "Some build description", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - BucketLabels: map[string]string{}, - BuildLabels: map[string]string{}, - }, - }, - }, - }, - }, + Type: "file.test", + Prepared: true, + BuildName: "test-file", + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, @@ -360,36 +184,9 @@ func TestRegistrySetup(t *testing.T) { "content": " ", "target": "output", }, - Builder: &packer.RegistryBuilder{ - Name: "file", - Builder: &file.Builder{}, - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - BucketLabels: map[string]string{}, - BuildLabels: map[string]string{}, - }, - }, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{ - { - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: "file", - ArtifactMetadataPublisher: ®istry.Bucket{ - Slug: "bucket-slug", - Description: "", - Iteration: ®istry.Iteration{}, - SourceImagesToParentIterations: map[string]registry.ParentIteration{}, - BucketLabels: map[string]string{}, - BuildLabels: map[string]string{}, - }, - }, - }, - }, - }, + Builder: &file.Builder{}, + Provisioners: []packer.CoreBuildProvisioner{}, + PostProcessors: [][]packer.CoreBuildPostProcessor{}, }, }, false, diff --git a/hcl2template/common_test.go b/hcl2template/common_test.go index 567959e21..2dd0ef6ba 100644 --- a/hcl2template/common_test.go +++ b/hcl2template/common_test.go @@ -359,7 +359,6 @@ var cmpOpts = []cmp.Option{ null.Builder{}, packerregistry.Bucket{}, packerregistry.Iteration{}, - packer.RegistryBuilder{}, ), cmpopts.IgnoreFields(PackerConfig{}, "Cwd", // Cwd will change for every os type diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 4595c5748..ffa95089f 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -545,14 +545,6 @@ func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceUseBlock, block continue } - if cfg.Bucket != nil { - postProcessor = &packer.RegistryPostProcessor{ - ArtifactMetadataPublisher: cfg.Bucket, - BuilderType: source.String(), - PostProcessor: postProcessor, - } - } - pps = append(pps, packer.CoreBuildPostProcessor{ PostProcessor: postProcessor, PName: ppb.PName, @@ -686,17 +678,6 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Bu continue } - if cfg.Bucket != nil { - pps = append(pps, []packer.CoreBuildPostProcessor{ - { - PostProcessor: &packer.RegistryPostProcessor{ - BuilderType: srcUsage.String(), - ArtifactMetadataPublisher: cfg.Bucket, - }, - }, - }) - } - if build.ErrorCleanupProvisionerBlock != nil { if !build.ErrorCleanupProvisionerBlock.OnlyExcept.Skip(srcUsage.String()) { errorCleanupProv, moreDiags := cfg.getCoreBuildProvisioner(srcUsage, build.ErrorCleanupProvisionerBlock, cfg.EvalContext(BuildContext, variables)) @@ -708,14 +689,6 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Bu } } - if cfg.Bucket != nil && cfg.Bucket.Validate() == nil { - builder = &packer.RegistryBuilder{ - Name: srcUsage.String(), - Builder: builder, - ArtifactMetadataPublisher: cfg.Bucket, - } - } - pcb.Builder = builder pcb.Provisioners = provisioners pcb.PostProcessors = pps diff --git a/packer/registry_artifact.go b/internal/registry/registry_artifact.go similarity index 97% rename from packer/registry_artifact.go rename to internal/registry/registry_artifact.go index ea954dbaa..57f8d771f 100644 --- a/packer/registry_artifact.go +++ b/internal/registry/registry_artifact.go @@ -1,4 +1,4 @@ -package packer +package registry import ( "fmt" diff --git a/internal/registry/types.bucket.go b/internal/registry/types.bucket.go index f45c279e6..ecb0cad29 100644 --- a/internal/registry/types.bucket.go +++ b/internal/registry/types.bucket.go @@ -11,8 +11,10 @@ import ( "github.com/hashicorp/go-multierror" "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" + "github.com/hashicorp/packer-plugin-sdk/packer" registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image" "github.com/hashicorp/packer/internal/registry/env" + "github.com/mitchellh/mapstructure" "google.golang.org/grpc/codes" ) @@ -28,6 +30,7 @@ type Bucket struct { BucketLabels map[string]string BuildLabels map[string]string SourceImagesToParentIterations map[string]ParentIteration + RunningBuilds map[string]chan struct{} Iteration *Iteration client *Client } @@ -44,6 +47,7 @@ func NewBucketWithIteration() *Bucket { BucketLabels: make(map[string]string), BuildLabels: make(map[string]string), SourceImagesToParentIterations: make(map[string]ParentIteration), + RunningBuilds: make(map[string]chan struct{}), } b.Iteration = NewIteration() @@ -403,7 +407,6 @@ func (b *Bucket) PopulateIteration(ctx context.Context) error { // IsExpectingBuildForComponent returns true if the component referenced by buildName is part of the iteration // and is not marked as DONE on the HCP Packer registry. func (b *Bucket) IsExpectingBuildForComponent(buildName string) bool { - if !b.Iteration.HasBuild(buildName) { return false } @@ -469,3 +472,108 @@ func (b *Bucket) HeartbeatBuild(ctx context.Context, build string) (func(), erro close(heartbeatChan) }, nil } + +func (b *Bucket) BuildStart(ctx context.Context, buildName string) error { + if !b.IsExpectingBuildForComponent(buildName) { + return fmt.Errorf("already done") + } + + err := b.UpdateBuildStatus(ctx, buildName, models.HashicorpCloudPackerBuildStatusRUNNING) + if err != nil { + return fmt.Errorf("failed to update HCP Packer registry status for %q: %s", buildName, err) + } + + cleanupHeartbeat, err := b.HeartbeatBuild(ctx, buildName) + if err != nil { + log.Printf("[ERROR] failed to start heartbeat function") + } + + buildDone := make(chan struct{}, 1) + go func() { + log.Printf("[TRACE] waiting for heartbeat completion") + select { + case <-ctx.Done(): + cleanupHeartbeat() + err := b.UpdateBuildStatus( + context.Background(), + buildName, + models.HashicorpCloudPackerBuildStatusCANCELLED) + if err != nil { + log.Printf( + "[ERROR] failed to update HCP Packer registry status for %q: %s", + buildName, + err) + } + case <-buildDone: + cleanupHeartbeat() + } + log.Printf("[TRACE] done waiting for heartbeat completion") + }() + + b.RunningBuilds[buildName] = buildDone + + return nil +} + +func (b *Bucket) BuildDone( + ctx context.Context, + buildName string, + artifacts []packer.Artifact, + buildErr error, +) ([]packer.Artifact, error) { + doneCh, ok := b.RunningBuilds[buildName] + if !ok { + log.Print("[ERROR] done build does not have an entry in the heartbeat table, state will be inconsistent.") + } else { + log.Printf("[TRACE] signal stopping heartbeats") + // Stop heartbeating + doneCh <- struct{}{} + log.Printf("[TRACE] stopped heartbeats") + } + + if buildErr != nil { + err := b.UpdateBuildStatus(ctx, buildName, models.HashicorpCloudPackerBuildStatusFAILED) + if err != nil { + log.Printf("[ERROR] failed to update build %q status to FAILED: %s", buildName, err) + } + return artifacts, fmt.Errorf("build failed, not uploading artifacts") + } + + for _, art := range artifacts { + var images []registryimage.Image + decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + Result: &images, + WeaklyTypedInput: true, + ErrorUnused: false, + }) + if err != nil { + return artifacts, fmt.Errorf("failed to create decoder for HCP Packer registry image: %w", err) + } + + state := art.State(registryimage.ArtifactStateURI) + err = decoder.Decode(state) + if err != nil { + return artifacts, fmt.Errorf("failed to obtain HCP Packer registry image from post-processor artifact: %w", err) + } + log.Printf("[TRACE] updating artifacts for build %q", buildName) + err = b.UpdateImageForBuild(buildName, images...) + + if err != nil { + return artifacts, fmt.Errorf("failed to add image artifact for %q: %s", buildName, err) + } + } + + parErr := b.CompleteBuild(ctx, buildName) + if parErr != nil { + return artifacts, fmt.Errorf( + "failed to update Packer registry with image artifacts for %q: %s", + buildName, + parErr) + } + + return append(artifacts, &RegistryArtifact{ + BuildName: buildName, + BucketSlug: b.Slug, + IterationID: b.Iteration.ID, + }), nil +} diff --git a/packer/core.go b/packer/core.go index 8556e4b1c..a634bffde 100644 --- a/packer/core.go +++ b/packer/core.go @@ -338,10 +338,6 @@ func (c *Core) Build(n string) (packersdk.Build, error) { // rawName is the uninterpolated name that we use for various lookups rawName := configBuilder.Name - // hcpName is the name we use for HCP, i.e. a concatenation of type+name - // if both are specified. - hcpName := HCPName(configBuilder) - // Setup the provisioners for this build provisioners := make([]CoreBuildProvisioner, 0, len(c.Template.Provisioners)) for _, rawP := range c.Template.Provisioners { @@ -399,14 +395,6 @@ func (c *Core) Build(n string) (packersdk.Build, error) { "post-processor type not found: %s", rawP.Type) } - if c.Bucket != nil { - postProcessor = &RegistryPostProcessor{ - BuilderType: hcpName, - ArtifactMetadataPublisher: c.Bucket, - PostProcessor: postProcessor, - } - } - current = append(current, CoreBuildPostProcessor{ PostProcessor: postProcessor, PType: rawP.Type, @@ -423,27 +411,9 @@ func (c *Core) Build(n string) (packersdk.Build, error) { postProcessors = append(postProcessors, current) } - if c.Bucket != nil { - postProcessors = append(postProcessors, []CoreBuildPostProcessor{ - { - PostProcessor: &RegistryPostProcessor{ - BuilderType: hcpName, - ArtifactMetadataPublisher: c.Bucket, - }, - }, - }) - } // TODO hooks one day - if c.Bucket != nil { - builder = &RegistryBuilder{ - Name: hcpName, - ArtifactMetadataPublisher: c.Bucket, - Builder: builder, - } - } - // Return a structure that contains the plugins, their types, variables, and // the raw builder config loaded from the json template return &CoreBuild{ diff --git a/packer/registry_builder.go b/packer/registry_builder.go deleted file mode 100644 index 3374da4e9..000000000 --- a/packer/registry_builder.go +++ /dev/null @@ -1,102 +0,0 @@ -package packer - -import ( - "context" - "fmt" - "log" - - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image" - packerregistry "github.com/hashicorp/packer/internal/registry" - "github.com/mitchellh/mapstructure" -) - -type RegistryBuilder struct { - Name string - ArtifactMetadataPublisher *packerregistry.Bucket - packersdk.Builder -} - -func (b *RegistryBuilder) Prepare(raws ...interface{}) ([]string, []string, error) { - return b.Builder.Prepare(raws...) -} - -// Run is where the actual build should take place. It takes a Build and a Ui. -func (b *RegistryBuilder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - - if !b.ArtifactMetadataPublisher.IsExpectingBuildForComponent(b.Name) { - ui.Error(fmt.Sprintf("The build for %q in iteration %q has already been marked as DONE; Skipping build to prevent drift.", b.Name, b.ArtifactMetadataPublisher.Iteration.ID)) - return nil, nil - } - - runCompleted := make(chan struct{}) - go func() { - for { - select { - case <-ctx.Done(): - log.Printf("[TRACE] marking build %q as cancelled in HCP Packer registry", b.Name) - if err := b.ArtifactMetadataPublisher.UpdateBuildStatus(context.TODO(), b.Name, models.HashicorpCloudPackerBuildStatusCANCELLED); err != nil { - log.Printf("[TRACE] failed to update HCP Packer registry status for %q: %s", b.Name, err) - } - return - case <-runCompleted: - return - } - } - }() - - if err := b.ArtifactMetadataPublisher.UpdateBuildStatus(ctx, b.Name, models.HashicorpCloudPackerBuildStatusRUNNING); err != nil { - log.Printf("[TRACE] failed to update HCP Packer registry status for %q: %s", b.Name, err) - } - - cleanupHeartbeat, err := b.ArtifactMetadataPublisher.HeartbeatBuild(ctx, b.Name) - if err != nil { - log.Printf("[ERROR] failed to start heartbeat function") - } - if cleanupHeartbeat != nil { - defer cleanupHeartbeat() - } - - ui.Say(fmt.Sprintf("Publishing build details for %s to the HCP Packer registry", b.Name)) - artifact, err := b.Builder.Run(ctx, ui, hook) - if err != nil { - if parErr := b.ArtifactMetadataPublisher.UpdateBuildStatus(ctx, b.Name, models.HashicorpCloudPackerBuildStatusFAILED); parErr != nil { - log.Printf("[TRACE] failed to update HCP Packer registry status for %q: %s", b.Name, parErr) - } - } - - // close chan to mark completion - close(runCompleted) - - if err != nil { - return nil, err - } - - if artifact == nil { - return nil, nil - } - - var images []registryimage.Image - decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - Result: &images, - WeaklyTypedInput: true, - ErrorUnused: false, - }) - if err != nil { - return artifact, fmt.Errorf("failed to create decoder for HCP Packer registry image: %w", err) - } - - state := artifact.State(registryimage.ArtifactStateURI) - err = decoder.Decode(state) - if err != nil { - return artifact, fmt.Errorf("failed to obtain HCP Packer registry image from build artifact: %w", err) - } - - err = b.ArtifactMetadataPublisher.UpdateImageForBuild(b.Name, images...) - if err != nil { - return artifact, fmt.Errorf("failed to add image artifact for %q: %s", b.Name, err) - } - - return artifact, nil -} diff --git a/packer/registry_post_processor.go b/packer/registry_post_processor.go deleted file mode 100644 index 25804e763..000000000 --- a/packer/registry_post_processor.go +++ /dev/null @@ -1,106 +0,0 @@ -package packer - -import ( - "context" - "fmt" - "log" - - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image" - packerregistry "github.com/hashicorp/packer/internal/registry" - "github.com/mitchellh/mapstructure" -) - -type RegistryPostProcessor struct { - BuilderType string - ArtifactMetadataPublisher *packerregistry.Bucket - packersdk.PostProcessor -} - -func (p *RegistryPostProcessor) ConfigSpec() hcldec.ObjectSpec { - if p.PostProcessor == nil { - return nil - } - - return p.PostProcessor.ConfigSpec() -} - -func (p *RegistryPostProcessor) Configure(raws ...interface{}) error { - if p.PostProcessor == nil { - return nil - } - - return p.PostProcessor.Configure(raws...) -} - -func (p *RegistryPostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, source packersdk.Artifact) (packersdk.Artifact, bool, bool, error) { - // This is a bit of a hack for now to denote that this pp should just update the state of a build in the Packer registry. - // TODO create an actual post-processor that we can embed here that will do the updating and printing. - if p.PostProcessor == nil { - if parErr := p.ArtifactMetadataPublisher.CompleteBuild(ctx, p.BuilderType); parErr != nil { - err := fmt.Errorf("[TRACE] failed to update Packer registry with image artifacts for %q: %s", p.BuilderType, parErr) - return nil, false, true, err - } - - r := &RegistryArtifact{ - BuildName: p.BuilderType, - BucketSlug: p.ArtifactMetadataPublisher.Slug, - IterationID: p.ArtifactMetadataPublisher.Iteration.ID, - } - - return r, true, false, nil - } - - // Bump build status first so we don't end-up chaining post-processors - // that don't heartbeat, hence letting too long happen between two - // refreshes, and letting the build go to the FAILED status. - err := p.ArtifactMetadataPublisher.UpdateBuildStatus( - ctx, - p.BuilderType, - models.HashicorpCloudPackerBuildStatusRUNNING, - ) - if err != nil { - log.Printf("[TRACE] failed to heartbeat running build %s: %s", p.BuilderType, err) - } - - cleanupHeartbeat, err := p.ArtifactMetadataPublisher.HeartbeatBuild(ctx, p.BuilderType) - if err != nil { - log.Printf("[ERROR] failed to start heartbeat function") - } - if cleanupHeartbeat != nil { - defer cleanupHeartbeat() - } - - source, keep, override, err := p.PostProcessor.PostProcess(ctx, ui, source) - if err != nil { - if parErr := p.ArtifactMetadataPublisher.UpdateBuildStatus(ctx, p.BuilderType, models.HashicorpCloudPackerBuildStatusFAILED); parErr != nil { - log.Printf("[TRACE] failed to update Packer registry with image artifacts for %q: %s", p.BuilderType, parErr) - } - return source, false, false, err - } - - var images []registryimage.Image - decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - Result: &images, - WeaklyTypedInput: true, - ErrorUnused: false, - }) - if err != nil { - return source, false, false, fmt.Errorf("failed to create decoder for HCP Packer registry image: %w", err) - } - - state := source.State(registryimage.ArtifactStateURI) - err = decoder.Decode(state) - if err != nil { - return source, false, false, fmt.Errorf("failed to obtain HCP Packer registry image from post-processor artifact: %w", err) - } - err = p.ArtifactMetadataPublisher.UpdateImageForBuild(p.BuilderType, images...) - - if err != nil { - return source, keep, override, fmt.Errorf("[TRACE] failed to add image artifact for %q: %s", p.BuilderType, err) - } - - return source, keep, override, nil -}