tmp: move HCP logic to unwrap builds/post

pull/12111/head
Lucas Bajolet 4 years ago committed by Lucas Bajolet
parent f0d0a0e6c5
commit f3e4c2c3bb

@ -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,

@ -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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
BuildLabels: map[string]string{"python_version": "3.0"},
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.test",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
BuildLabels: map[string]string{"python_version": "3.0"},
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
BuildLabels: map[string]string{"python_version": "3.0"},
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.other",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
BuildLabels: map[string]string{"python_version": "3.0"},
Iteration: &registry.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: &registry.Bucket{
Slug: "real-bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.test",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "real-bucket-slug",
Description: "Some description\n",
BucketLabels: map[string]string{"foo": "bar"},
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some build description",
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.test",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some build description",
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some override description",
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.test",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some override description",
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
BucketLabels: map[string]string{"foo": "bar"},
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
},
},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{
PostProcessor: &packer.RegistryPostProcessor{
BuilderType: "file.test",
ArtifactMetadataPublisher: &registry.Bucket{
Slug: "bucket-slug",
BucketLabels: map[string]string{"foo": "bar"},
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some build description",
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "Some build description",
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "",
Iteration: &registry.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: &registry.Bucket{
Slug: "bucket-slug",
Description: "",
Iteration: &registry.Iteration{},
SourceImagesToParentIterations: map[string]registry.ParentIteration{},
BucketLabels: map[string]string{},
BuildLabels: map[string]string{},
},
},
},
},
},
Builder: &file.Builder{},
Provisioners: []packer.CoreBuildProvisioner{},
PostProcessors: [][]packer.CoreBuildPostProcessor{},
},
},
false,

@ -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

@ -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

@ -1,4 +1,4 @@
package packer
package registry
import (
"fmt"

@ -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
}

@ -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{

@ -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
}

@ -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
}
Loading…
Cancel
Save