Skip to content

Commit

Permalink
hcp: extract all HCP-related code to hcp package
Browse files Browse the repository at this point in the history
As part of the work to displace everything related to HCP from scattered
places around the Packer code, we move it all to an hcp package.

This in turn reduces the amount of code that the commands have to
integrate, and leaves the HCP details to its own enclave.
  • Loading branch information
lbajolet-hashicorp committed Oct 25, 2022
1 parent 9b9ab46 commit 0a80100
Show file tree
Hide file tree
Showing 21 changed files with 417 additions and 671 deletions.
4 changes: 2 additions & 2 deletions acctest/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ func Test(t TestT, c TestCase) {
},
Template: tpl,
})
err = core.Initialize()
if err != nil {
diags := core.Initialize(packer.InitializeOptions{})
if diags.HasErrors() {
t.Fatal(fmt.Sprintf("Failed to init core: %s", err))
return
}
Expand Down
121 changes: 45 additions & 76 deletions command/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package command
import (
"bytes"
"context"
"errors"
"fmt"
"log"
"math"
Expand All @@ -13,6 +14,7 @@ import (

"github.com/hashicorp/hcl/v2"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/internal/hcp"
"github.com/hashicorp/packer/packer"
"golang.org/x/sync/semaphore"

Expand Down Expand Up @@ -88,35 +90,21 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
return ret
}

diags = TrySetupHCP(packerStarter)
hcpHandler, diags := hcp.GetOrchestrator(packerStarter)
ret = writeDiags(c.Ui, nil, diags)
if ret != 0 {
return ret
}

// This build currently enforces a 1:1 mapping that one publisher can be assigned to a single packer config file.
// It also requires that each config type implements this ConfiguredArtifactMetadataPublisher to return a configured bucket.
// TODO find an option that is not managed by a globally shared Publisher.
ArtifactMetadataPublisher, diags := packerStarter.ConfiguredArtifactMetadataPublisher()
if diags.HasErrors() {
return writeDiags(c.Ui, nil, diags)
}

// We need to create a bucket and an empty iteration before we retrieve builds
// so that we can add the iteration ID to the build's eval context
if ArtifactMetadataPublisher != nil {
if err := ArtifactMetadataPublisher.Initialize(buildCtx); err != nil {
diags := hcl.Diagnostics{
&hcl.Diagnostic{
Summary: "Failed to get HCP Packer Registry iteration",
Detail: fmt.Sprintf("Packer could not create an iteration or "+
"link the build to an existing iteration. Contact HCP Packer "+
"support for further assistance.\nError: %s", err),
Severity: hcl.DiagError,
},
}
return writeDiags(c.Ui, nil, diags)
}
err := hcpHandler.PopulateIteration(buildCtx)
if err != nil {
return writeDiags(c.Ui, nil, hcl.Diagnostics{
&hcl.Diagnostic{
Summary: "HCP: populating iteration failed",
Severity: hcl.DiagError,
Detail: err.Error(),
},
})
}

builds, hcpMap, diags := packerStarter.GetBuilds(packer.GetBuildsOptions{
Expand All @@ -138,23 +126,6 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
c.Ui.Say("Debug mode enabled. Builds will not be parallelized.")
}

// Now that builds have been retrieved, we can populate the iteration with
// the builds we expect to run.
if ArtifactMetadataPublisher != nil {
if err := ArtifactMetadataPublisher.PopulateIteration(buildCtx); err != nil {
diags := hcl.Diagnostics{
&hcl.Diagnostic{
Summary: "Failed to register builds to the HCP Packer registry iteration",
Detail: fmt.Sprintf("Packer could not register builds within your "+
"configuration to the iteration. Contact HCP Packer support "+
"for further assistance.\nError: %s", err),
Severity: hcl.DiagError,
},
}
return writeDiags(c.Ui, nil, diags)
}
}

// Compile all the UIs for the builds
colors := [5]packer.UiColor{
packer.UiColorGreen,
Expand Down Expand Up @@ -215,7 +186,7 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
m map[string][]packersdk.Artifact
}{m: make(map[string][]packersdk.Artifact)}
// Get the builds we care about
var errors = struct {
var errs = struct {
sync.RWMutex
m map[string]error
}{m: make(map[string]error)}
Expand All @@ -231,9 +202,9 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
ui := buildUis[b]
if err := limitParallel.Acquire(buildCtx, 1); err != nil {
ui.Error(fmt.Sprintf("Build '%s' failed to acquire semaphore: %s", name, err))
errors.Lock()
errors.m[name] = err
errors.Unlock()
errs.Lock()
errs.m[name] = err
errs.Unlock()
break
}
// Increment the waitgroup so we wait for this item to finish properly
Expand All @@ -248,19 +219,13 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int

defer limitParallel.Release(1)

if ArtifactMetadataPublisher != nil {
err := ArtifactMetadataPublisher.BuildStart(buildCtx, hcpMap[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
}

err := hcpHandler.BuildStart(buildCtx, hcpMap[name])
if err != nil {
if errors.As(err, &hcp.BuildDone{}) {
ui.Say(fmt.Sprintf(
"skipping HCP-enabled build %q: already done.",
name))
return
}
}

Expand All @@ -272,24 +237,28 @@ 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,
hcpMap[name],
runArtifacts,
err,
)
if err != nil {
ui.Error(fmt.Sprintf("failed to complete HCP build %q: %s",
name, err))
}
runArtifacts, hcperr := hcpHandler.BuildDone(
buildCtx,
hcpMap[name],
runArtifacts,
err)
if hcperr != nil {
writeDiags(c.Ui, nil, hcl.Diagnostics{
&hcl.Diagnostic{
Summary: fmt.Sprintf(
"failed to complete HCP-enabled build %q",
name),
Severity: hcl.DiagError,
Detail: hcperr.Error(),
},
})
}

if err != nil {
ui.Error(fmt.Sprintf("Build '%s' errored after %s: %s", name, fmtBuildDuration, err))
errors.Lock()
errors.m[name] = err
errors.Unlock()
errs.Lock()
errs.m[name] = err
errs.Unlock()
} else {
ui.Say(fmt.Sprintf("Build '%s' finished after %s.", name, fmtBuildDuration))
if runArtifacts != nil {
Expand Down Expand Up @@ -327,11 +296,11 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
return 1
}

if len(errors.m) > 0 {
c.Ui.Machine("error-count", strconv.FormatInt(int64(len(errors.m)), 10))
if len(errs.m) > 0 {
c.Ui.Machine("error-count", strconv.FormatInt(int64(len(errs.m)), 10))

c.Ui.Error("\n==> Some builds didn't complete successfully and had errors:")
for name, err := range errors.m {
for name, err := range errs.m {
// Create a UI for the machine readable stuff to be targeted
ui := &packer.TargetedUI{
Target: name,
Expand Down Expand Up @@ -394,7 +363,7 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
c.Ui.Say("\n==> Builds finished but no artifacts were created.")
}

if len(errors.m) > 0 {
if len(errs.m) > 0 {
// If any errors occurred, exit with a non-zero exit status
ret = 1
}
Expand Down
72 changes: 0 additions & 72 deletions command/core_wrapper.go

This file was deleted.

4 changes: 2 additions & 2 deletions command/hcl2_upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ func (c *HCL2UpgradeCommand) RunContext(_ context.Context, cla *HCL2UpgradeArgs)
return 1
}

core := hdl.(*CoreWrapper).Core
if err := core.Initialize(); err != nil {
core := hdl.(*packer.Core)
if err := core.Initialize(packer.InitializeOptions{}); err != nil {
c.Ui.Error(fmt.Sprintf("Ignoring following initialization error: %v", err))
}
tpl := core.Template
Expand Down
2 changes: 1 addition & 1 deletion command/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,5 @@ func (m *Meta) GetConfigFromJSON(cla *MetaArgs) (packer.Handler, int) {
m.Ui.Error(err.Error())
ret = 1
}
return &CoreWrapper{core}, ret
return core, ret
}
Loading

0 comments on commit 0a80100

Please sign in to comment.