From 1cee460d0d05cccc690dd446f9b8470e03d17f4b Mon Sep 17 00:00:00 2001 From: Lucas Bajolet Date: Tue, 6 Sep 2022 17:26:49 -0400 Subject: [PATCH] hcp: extract all HCP-related code to hcp package 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. --- acctest/testing.go | 4 +- command/build.go | 121 ++++----- command/core_wrapper.go | 72 ----- command/hcl2_upgrade.go | 4 +- command/meta.go | 2 +- command/registry_test.go | 292 --------------------- hcl2template/common_test.go | 3 +- hcl2template/parser.go | 1 + hcl2template/registry.go | 40 --- hcl2template/types.packer_config.go | 17 +- internal/hcp/bucket_init.go | 84 ++++++ internal/hcp/errors.go | 13 + command/registry.go => internal/hcp/hcl.go | 191 ++++---------- internal/hcp/json.go | 83 ++++++ internal/hcp/noop.go | 31 +++ internal/hcp/orchestrator.go | 34 +++ internal/registry/types.bucket.go | 9 +- packer/core.go | 38 ++- packer/core_test.go | 36 +-- packer/run_interfaces.go | 11 +- packer/testing.go | 2 +- 21 files changed, 417 insertions(+), 671 deletions(-) delete mode 100644 command/core_wrapper.go delete mode 100644 command/registry_test.go delete mode 100644 hcl2template/registry.go create mode 100644 internal/hcp/bucket_init.go create mode 100644 internal/hcp/errors.go rename command/registry.go => internal/hcp/hcl.go (56%) create mode 100644 internal/hcp/json.go create mode 100644 internal/hcp/noop.go create mode 100644 internal/hcp/orchestrator.go diff --git a/acctest/testing.go b/acctest/testing.go index dc0af792c..2a9d3bca7 100644 --- a/acctest/testing.go +++ b/acctest/testing.go @@ -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 } diff --git a/command/build.go b/command/build.go index 4a3278ad8..2166d3b26 100644 --- a/command/build.go +++ b/command/build.go @@ -3,6 +3,7 @@ package command import ( "bytes" "context" + "errors" "fmt" "log" "math" @@ -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" @@ -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{ @@ -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, @@ -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)} @@ -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 @@ -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 } } @@ -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 { @@ -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, @@ -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 } diff --git a/command/core_wrapper.go b/command/core_wrapper.go deleted file mode 100644 index 85207a8be..000000000 --- a/command/core_wrapper.go +++ /dev/null @@ -1,72 +0,0 @@ -package command - -import ( - "fmt" - - "github.com/hashicorp/hcl/v2" - packerregistry "github.com/hashicorp/packer/internal/registry" - "github.com/hashicorp/packer/packer" - plugingetter "github.com/hashicorp/packer/packer/plugin-getter" -) - -// CoreWrapper wraps a packer.Core in order to have it's Initialize func return -// a diagnostic. -type CoreWrapper struct { - *packer.Core -} - -func (c *CoreWrapper) Initialize(_ packer.InitializeOptions) hcl.Diagnostics { - err := c.Core.Initialize() - if err != nil { - return hcl.Diagnostics{ - &hcl.Diagnostic{ - Detail: err.Error(), - Severity: hcl.DiagError, - }, - } - } - return nil -} - -func (c *CoreWrapper) PluginRequirements() (plugingetter.Requirements, hcl.Diagnostics) { - return nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: "Packer plugins currently only works with HCL2 configuration templates", - Detail: "Please manually install plugins with the plugins command or use a HCL2 configuration that will do that for you.", - Severity: hcl.DiagError, - }, - } -} - -// ConfiguredArtifactMetadataPublisher returns a configured image bucket that can be used for publishing -// build image artifacts to a configured Packer Registry destination. -func (c *CoreWrapper) ConfiguredArtifactMetadataPublisher() (*packerregistry.Bucket, hcl.Diagnostics) { - bucket := c.Core.GetRegistryBucket() - - // If at this point the bucket is nil, it means the HCP Packer registry is not enabled - if bucket == nil { - return nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: "Publishing build artifacts to HCP Packer Registry not enabled", - Detail: "No Packer Registry configuration detected; skipping all publishing steps " + - "See publishing to a Packer registry for Packer configuration details", - Severity: hcl.DiagWarning, - }, - } - } - - err := bucket.Validate() - if err != nil { - return nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: "Invalid HCP Packer configuration", - Detail: fmt.Sprintf("Packer could not validate the provided "+ - "HCP Packer registry configuration. Check the error message for details "+ - "or contact HCP Packer support for further assistance.\nError: %s", err), - Severity: hcl.DiagError, - }, - } - } - - return bucket, nil -} diff --git a/command/hcl2_upgrade.go b/command/hcl2_upgrade.go index 2c04f01a0..a9dec8251 100644 --- a/command/hcl2_upgrade.go +++ b/command/hcl2_upgrade.go @@ -159,8 +159,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 diff --git a/command/meta.go b/command/meta.go index bf5a6d662..d6ad45ae9 100644 --- a/command/meta.go +++ b/command/meta.go @@ -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 } diff --git a/command/registry_test.go b/command/registry_test.go deleted file mode 100644 index 5997880b9..000000000 --- a/command/registry_test.go +++ /dev/null @@ -1,292 +0,0 @@ -package command - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/hcl/v2" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer/builder/file" - "github.com/hashicorp/packer/hcl2template" - "github.com/hashicorp/packer/internal/registry" - "github.com/hashicorp/packer/packer" -) - -type registryTestArgs struct { - name string - inputFilePath string - expectedBuilds []packersdk.Build - expectError bool - envvars map[string]string -} - -var registryCmpOpts = cmp.Options{ - cmpopts.IgnoreFields( - registry.Iteration{}, - "Fingerprint", - ), - cmpopts.IgnoreFields( - packer.CoreBuild{}, - "TemplatePath", - "Variables", - ), - cmpopts.IgnoreUnexported( - hcl2template.PackerConfig{}, - hcl2template.Variable{}, - hcl2template.SourceBlock{}, - hcl2template.DatasourceBlock{}, - hcl2template.ProvisionerBlock{}, - hcl2template.PostProcessorBlock{}, - packer.CoreBuild{}, - hcl2template.HCL2Provisioner{}, - hcl2template.HCL2PostProcessor{}, - packer.CoreBuildPostProcessor{}, - packer.CoreBuildProvisioner{}, - packer.CoreBuildPostProcessor{}, - file.Builder{}, - registry.Bucket{}, - registry.Iteration{}, - ), -} - -func TestRegistrySetup(t *testing.T) { - tests := []registryTestArgs{ - { - "HCL2 - hcp_registry_block and multiple sources", - "test-fixtures/hcp/multiple_sources.pkr.hcl", - []packersdk.Build{ - &packer.CoreBuild{ - 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: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{}, - }, - { - "HCL2 - set slug in hcp packer registry block", - "test-fixtures/hcp/slug.pkr.hcl", - []packersdk.Build{ - &packer.CoreBuild{ - BuildName: "bucket-slug", - Type: "file.test", - Prepared: true, - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{}, - }, - { - "HCL2 - hcp - use build description", - "test-fixtures/hcp/build-description.pkr.hcl", - []packersdk.Build{ - &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - BuildName: "bucket-slug", - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{}, - }, - { - "HCL2 - override build description with hcp packer registry description", - "test-fixtures/hcp/override-build-description.pkr.hcl", - []packersdk.Build{ - &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{}, - }, - { - "HCL2 - deprecated labels in hcp packer registry block", - "test-fixtures/hcp/deprecated_labels.pkr.hcl", - []packersdk.Build{ - &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - true, - map[string]string{}, - }, - { - "HCL2 - duplicate hcp_registry blocks", - "test-fixtures/hcp/duplicate.pkr.hcl", - nil, - true, - map[string]string{}, - }, - { - "HCL2 - two build blocks with hcp_registry", - "test-fixtures/hcp/dup_build_blocks.pkr.hcl", - nil, - true, - map[string]string{}, - }, - { - "HCL2/JSON - hcp enabled build", - "test-fixtures/hcp/hcp_normal.pkr.json", - []packersdk.Build{ - &packer.CoreBuild{ - Type: "file.test", - Prepared: true, - BuildName: "test-file", - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{ - "HCP_PACKER_REGISTRY": "1", - "HCP_PACKER_BUCKET_NAME": "bucket-slug", - }, - }, - { - "Legacy JSON - hcp enabled build", - "test-fixtures/hcp/hcp_build.json", - []packersdk.Build{ - &packer.CoreBuild{ - Type: "file", - Prepared: false, - BuildName: "", - BuilderType: "file", - BuilderConfig: map[string]interface{}{ - "content": " ", - "target": "output", - }, - Builder: &file.Builder{}, - Provisioners: []packer.CoreBuildProvisioner{}, - PostProcessors: [][]packer.CoreBuildPostProcessor{}, - }, - }, - false, - map[string]string{ - "HCP_PACKER_REGISTRY": "1", - "HCP_PACKER_BUCKET_NAME": "bucket-slug", - }, - }, - } - - t.Setenv("HCP_CLIENT_ID", "test") - t.Setenv("HCP_CLIENT_SECRET", "test") - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - runRegistryTest(t, tt) - }) - } -} - -func runRegistryTest(t *testing.T, args registryTestArgs) { - for evar, val := range args.envvars { - t.Setenv(evar, val) - } - - defaultMeta := TestMetaFile(t) - - c := &BuildCommand{ - Meta: defaultMeta, - } - - cla := &BuildArgs{ - MetaArgs: MetaArgs{ - Path: args.inputFilePath, - }, - } - - packerStarter, ret := c.GetConfig(&cla.MetaArgs) - if ret != 0 { - t.Fatalf("failed to get packer config") - } - - diags := packerStarter.Initialize(packer.InitializeOptions{}) - if diagCheck(diags, t) { - return - } - - diags = TrySetupHCP(packerStarter) - if diagCheck(diags, t) { - if !args.expectError { - t.Errorf("SetupRegistry unexpectedly failed") - } - return - } - - builds, _, diags := packerStarter.GetBuilds(packer.GetBuildsOptions{ - Only: cla.Only, - Except: cla.Except, - Debug: cla.Debug, - Force: cla.Force, - OnError: cla.OnError, - }) - if diagCheck(diags, t) { - if !args.expectError { - t.Errorf("SetupRegistry unexpectedly failed") - } - return - } - - diff := cmp.Diff(builds, args.expectedBuilds, registryCmpOpts...) - if diff != "" { - t.Error(diff) - } -} - -func severityString(sev hcl.DiagnosticSeverity) string { - switch sev { - case hcl.DiagInvalid: - return "UNKNOWN" - case hcl.DiagError: - return "ERROR" - case hcl.DiagWarning: - return "WARNING" - } - panic("unknown severity") -} - -// diagCheck errors for each diagnostic received and returns if a diag was processed -func diagCheck(diags hcl.Diagnostics, t *testing.T) bool { - if len(diags) == 0 { - return false - } - - for _, d := range diags { - t.Logf( - "%s: %s - %s", - severityString(d.Severity), - d.Summary, - d.Detail, - ) - } - return true -} diff --git a/hcl2template/common_test.go b/hcl2template/common_test.go index 33b302524..e25e98f24 100644 --- a/hcl2template/common_test.go +++ b/hcl2template/common_test.go @@ -361,7 +361,8 @@ var cmpOpts = []cmp.Option{ packerregistry.Iteration{}, ), cmpopts.IgnoreFields(PackerConfig{}, - "Cwd", // Cwd will change for every os type + "Cwd", // Cwd will change for every os type + "HCPVars", // HCPVars will not be filled-in during parsing ), cmpopts.IgnoreFields(packerregistry.Iteration{}, "Fingerprint", // Fingerprint will change everytime diff --git a/hcl2template/parser.go b/hcl2template/parser.go index 76831731e..95b18ad1b 100644 --- a/hcl2template/parser.go +++ b/hcl2template/parser.go @@ -137,6 +137,7 @@ func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]st Basedir: basedir, Cwd: wd, CorePackerVersionString: p.CorePackerVersionString, + HCPVars: map[string]cty.Value{}, parser: p, files: files, } diff --git a/hcl2template/registry.go b/hcl2template/registry.go deleted file mode 100644 index f0642a823..000000000 --- a/hcl2template/registry.go +++ /dev/null @@ -1,40 +0,0 @@ -package hcl2template - -import ( - "fmt" - - "github.com/hashicorp/hcl/v2" - packerregistry "github.com/hashicorp/packer/internal/registry" -) - -// ConfiguredArtifactMetadataPublisher returns a configured image bucket that can be used for publishing -// build image artifacts to a configured Packer Registry destination. -func (cfg *PackerConfig) ConfiguredArtifactMetadataPublisher() (*packerregistry.Bucket, hcl.Diagnostics) { - // If this was a PAR (HCP Packer registry) build either the env. variables are set, or if there is a hcp_packer_registry block - // defined we would have a non-nil bucket. So if nil assume we are not in a some sort of PAR mode. - if cfg.Bucket == nil { - return nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: "Publishing build artifacts to HCP Packer Registry not enabled", - Detail: "No Packer Registry configuration detected; skipping all publishing steps " + - "See publishing to a Packer registry for Packer configuration details", - Severity: hcl.DiagWarning, - }, - } - } - - err := cfg.Bucket.Validate() - if err != nil { - return nil, hcl.Diagnostics{ - &hcl.Diagnostic{ - Summary: "Invalid HCP Packer configuration", - Detail: fmt.Sprintf("Packer could not validate the provided "+ - "HCP Packer registry configuration. Check the error message for details "+ - "or contact HCP Packer support for further assistance.\nError: %s", err), - Severity: hcl.DiagError, - }, - } - } - - return cfg.Bucket, nil -} diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index b135ac89a..55e0f80ea 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -7,12 +7,11 @@ import ( "strings" "github.com/gobwas/glob" - "github.com/hashicorp/hcl/v2" + hcl "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/hcl/v2/hclsyntax" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" pkrfunction "github.com/hashicorp/packer/hcl2template/function" - packerregistry "github.com/hashicorp/packer/internal/registry" "github.com/hashicorp/packer/packer" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/function" @@ -54,8 +53,8 @@ type PackerConfig struct { // Builds is the list of Build blocks defined in the config files. Builds Builds - // Represents registry bucket defined in the config files. - Bucket *packerregistry.Bucket + // HCPVars is the list of HCP-set variables for use later in a template + HCPVars map[string]cty.Value parser *Parser files []*hcl.File @@ -119,11 +118,13 @@ func (cfg *PackerConfig) EvalContext(ctx BlockContext, variables map[string]cty. }, } - // Store the iteration_id, if it exists. Otherwise, it'll be "unknown" - if cfg.Bucket != nil { + iterID, ok := cfg.HCPVars["iterationID"] + if ok { + log.Printf("iterationID set: %q", iterID) + ectx.Variables[packerAccessor] = cty.ObjectVal(map[string]cty.Value{ "version": cty.StringVal(cfg.CorePackerVersionString), - "iterationID": cty.StringVal(cfg.Bucket.Iteration.ID), + "iterationID": iterID, }) } @@ -576,7 +577,7 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Bu cfg.onError = opts.OnError if len(cfg.Builds) == 0 { - return res, append(diags, &hcl.Diagnostic{ + return res, hcpTranslationMap, append(diags, &hcl.Diagnostic{ Summary: "Missing build block", Detail: "A build block with one or more sources is required for executing a build.", Severity: hcl.DiagError, diff --git a/internal/hcp/bucket_init.go b/internal/hcp/bucket_init.go new file mode 100644 index 000000000..a6c3f8a42 --- /dev/null +++ b/internal/hcp/bucket_init.go @@ -0,0 +1,84 @@ +package hcp + +import ( + "fmt" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/packer/internal/registry" + "github.com/hashicorp/packer/internal/registry/env" +) + +// HCPConfigMode types specify the mode in which HCP configuration +// is defined for a given Packer build execution. +type HCPConfigMode int + +const ( + // HCPConfigUnset mode is set when no HCP configuration has been found for the Packer execution. + HCPConfigUnset HCPConfigMode = iota + // HCPConfigEnabled mode is set when the HCP configuration is codified in the template. + HCPConfigEnabled + // HCPEnvEnabled mode is set when the HCP configuration is read from environment variables. + HCPEnvEnabled +) + +type bucketConfigurationOpts func(*registry.Bucket) hcl.Diagnostics + +// createConfiguredBucket returns a bucket that can be used for connecting to the HCP Packer registry. +// Configuration for the bucket is obtained from the base iteration setting and any addition configuration +// options passed in as opts. All errors during configuration are collected and returned as Diagnostics. +func createConfiguredBucket(templateDir string, opts ...bucketConfigurationOpts) (*registry.Bucket, hcl.Diagnostics) { + var diags hcl.Diagnostics + + if !env.HasHCPCredentials() { + diags = append(diags, &hcl.Diagnostic{ + Summary: "HCP authentication information required", + Detail: fmt.Sprintf("The client authentication requires both %s and %s environment "+ + "variables to be set for authenticating with HCP.", + env.HCPClientID, + env.HCPClientSecret), + Severity: hcl.DiagError, + }) + } + + bucket := registry.NewBucketWithIteration() + + for _, opt := range opts { + if optDiags := opt(bucket); optDiags.HasErrors() { + diags = append(diags, optDiags...) + } + } + + if bucket.Slug == "" { + diags = append(diags, &hcl.Diagnostic{ + Summary: "Image bucket name required", + Detail: "You must provide an image bucket name for HCP Packer builds. " + + "You can set the HCP_PACKER_BUCKET_NAME environment variable. " + + "For HCL2 templates, the registry either uses the name of your " + + "template's build block, or you can set the bucket_name argument " + + "in an hcp_packer_registry block.", + Severity: hcl.DiagError, + }) + } + + err := bucket.Iteration.Initialize(registry.IterationOptions{ + TemplateBaseDir: templateDir, + }) + + if err != nil { + diags = append(diags, &hcl.Diagnostic{ + Summary: "Iteration initialization failed", + Detail: fmt.Sprintf("Initialization of the iteration failed with "+ + "the following error message: %s", err), + Severity: hcl.DiagError, + }) + } + return bucket, diags +} + +func withPackerEnvConfiguration(bucket *registry.Bucket) hcl.Diagnostics { + // Add default values for Packer settings configured via EnvVars. + // TODO look to break this up to be more explicit on what is loaded here. + bucket.LoadDefaultSettingsFromEnv() + + return nil +} diff --git a/internal/hcp/errors.go b/internal/hcp/errors.go new file mode 100644 index 000000000..b1d400603 --- /dev/null +++ b/internal/hcp/errors.go @@ -0,0 +1,13 @@ +package hcp + +import "fmt" + +// BuildDone is the error retuned by an HCP handler when a build cannot be started since it's already marked as DONE. +type BuildDone struct { + Message string +} + +// Error returns the message for the BuildDone type +func (b BuildDone) Error() string { + return fmt.Sprintf("BuildDone: %s", b.Message) +} diff --git a/command/registry.go b/internal/hcp/hcl.go similarity index 56% rename from command/registry.go rename to internal/hcp/hcl.go index ee8add83a..4ac370462 100644 --- a/command/registry.go +++ b/internal/hcp/hcl.go @@ -1,33 +1,25 @@ -package command +package hcp import ( + "context" "fmt" - "path/filepath" "github.com/hashicorp/hcl/v2" + sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer" imgds "github.com/hashicorp/packer/datasource/hcp-packer-image" iterds "github.com/hashicorp/packer/datasource/hcp-packer-iteration" "github.com/hashicorp/packer/hcl2template" "github.com/hashicorp/packer/internal/registry" "github.com/hashicorp/packer/internal/registry/env" - "github.com/hashicorp/packer/packer" - "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/gocty" ) -// HCPConfigMode types specify the mode in which HCP configuration -// is defined for a given Packer build execution. -type HCPConfigMode int - -const ( - // HCPConfigUnset mode is set when no HCP configuration has been found for the Packer execution. - HCPConfigUnset HCPConfigMode = iota - // HCPConfigEnabled mode is set when the HCP configuration is codified in the template. - HCPConfigEnabled - // HCPEnvEnabled mode is set when the HCP configuration is read from environment variables. - HCPEnvEnabled -) +// hclOrchestrator is a HCP handler made for handling HCL configurations +type hclOrchestrator struct { + configuration *hcl2template.PackerConfig + bucket *registry.Bucket +} const ( // Known HCP Packer Image Datasource, whose id is the SourceImageId for some build. @@ -36,53 +28,65 @@ const ( buildLabel string = "build" ) -// TrySetupHCP attempts to configure the HCP-related structures if -// Packer has been configured to publish to a HCP Packer registry. -func TrySetupHCP(cfg packer.Handler) hcl.Diagnostics { - switch cfg := cfg.(type) { - case *hcl2template.PackerConfig: - return setupRegistryForPackerConfig(cfg) - case *CoreWrapper: - return setupRegistryForPackerCore(cfg) +// PopulateIteration creates the metadata on HCP for a build +func (h *hclOrchestrator) PopulateIteration(ctx context.Context) error { + err := h.bucket.Initialize(ctx) + if err != nil { + return err } - return hcl.Diagnostics{ - &hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "unknown Handler type", - Detail: "TrySetupHCP called with an unknown Handler. " + - "This is a Packer bug and should be brought to the attention " + - "of the Packer team, please consider opening an issue for this.", - }, + err = h.bucket.PopulateIteration(ctx) + if err != nil { + return err } + + iterationID := h.bucket.Iteration.ID + + h.configuration.HCPVars["iterationID"] = cty.StringVal(iterationID) + + return nil } -func setupRegistryForPackerConfig(pc *hcl2template.PackerConfig) hcl.Diagnostics { +// BuildStart is invoked when one build for the configuration is starting to be processed +func (h *hclOrchestrator) BuildStart(ctx context.Context, buildName string) error { + return h.bucket.BuildStart(ctx, buildName) +} +// BuildDone is invoked when one build for the configuration has finished +func (h *hclOrchestrator) BuildDone( + ctx context.Context, + buildName string, + artifacts []sdkpacker.Artifact, + buildErr error, +) ([]sdkpacker.Artifact, error) { + return h.bucket.BuildDone(ctx, buildName, artifacts, buildErr) +} + +func newHCLOrchestrator(config *hcl2template.PackerConfig) (Orchestrator, hcl.Diagnostics) { // HCP_PACKER_REGISTRY is explicitly turned off if env.IsHCPDisabled() { - return nil + return newNoopHandler(), nil } mode := HCPConfigUnset - for _, build := range pc.Builds { + for _, build := range config.Builds { if build.HCPPackerRegistry != nil { mode = HCPConfigEnabled } } - // HCP_PACKER_BUCKET_NAME is set or HCP_PACKER_REGISTRY not toggled off + // HCP_PACKER_BUCKET_NAME is set or HCP_PACKER_REGISTRY not toggled off if mode == HCPConfigUnset && (env.HasPackerRegistryBucket() || env.IsHCPExplicitelyEnabled()) { mode = HCPEnvEnabled } if mode == HCPConfigUnset { - return nil + return newNoopHandler(), nil } var diags hcl.Diagnostics - if len(pc.Builds) > 1 { + if len(config.Builds) > 1 { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "Multiple " + buildLabel + " blocks", @@ -92,7 +96,7 @@ func setupRegistryForPackerConfig(pc *hcl2template.PackerConfig) hcl.Diagnostics "clear any HCP_PACKER_* environment variables."), }) - return diags + return nil, diags } withHCLBucketConfiguration := func(bb *hcl2template.BuildBlock) bucketConfigurationOpts { @@ -113,117 +117,34 @@ func setupRegistryForPackerConfig(pc *hcl2template.PackerConfig) hcl.Diagnostics } // Capture Datasource configuration data - vals, dsDiags := pc.Datasources.Values() + vals, dsDiags := config.Datasources.Values() if dsDiags != nil { diags = append(diags, dsDiags...) } - build := pc.Builds[0] - pc.Bucket, diags = createConfiguredBucket( - pc.Basedir, + build := config.Builds[0] + bucket, bucketDiags := createConfiguredBucket( + config.Basedir, withPackerEnvConfiguration, withHCLBucketConfiguration(build), withDatasourceConfiguration(vals), ) + if bucketDiags != nil { + diags = append(diags, bucketDiags...) + } if diags.HasErrors() { - return diags + return nil, diags } for _, source := range build.Sources { - pc.Bucket.RegisterBuildForComponent(source.String()) + bucket.RegisterBuildForComponent(source.String()) } - return diags -} - -func setupRegistryForPackerCore(cfg *CoreWrapper) hcl.Diagnostics { - if env.IsHCPDisabled() { - return nil - } - - if !env.HasPackerRegistryBucket() && !env.IsHCPExplicitelyEnabled() { - return nil - } - - bucket, diags := createConfiguredBucket( - filepath.Dir(cfg.Core.Template.Path), - withPackerEnvConfiguration, - ) - - if diags.HasErrors() { - return diags - } - - cfg.Core.Bucket = bucket - for _, b := range cfg.Core.Template.Builders { - // Get all builds slated within config ignoring any only or exclude flags. - cfg.Core.Bucket.RegisterBuildForComponent(packer.HCPName(b)) - } - - return diags -} - -type bucketConfigurationOpts func(*registry.Bucket) hcl.Diagnostics - -// createConfiguredBucket returns a bucket that can be used for connecting to the HCP Packer registry. -// Configuration for the bucket is obtained from the base iteration setting and any addition configuration -// options passed in as opts. All errors during configuration are collected and returned as Diagnostics. -func createConfiguredBucket(templateDir string, opts ...bucketConfigurationOpts) (*registry.Bucket, hcl.Diagnostics) { - var diags hcl.Diagnostics - - if !env.HasHCPCredentials() { - diags = append(diags, &hcl.Diagnostic{ - Summary: "HCP authentication information required", - Detail: fmt.Sprintf("The client authentication requires both %s and %s environment "+ - "variables to be set for authenticating with HCP.", - env.HCPClientID, - env.HCPClientSecret), - Severity: hcl.DiagError, - }) - } - - bucket := registry.NewBucketWithIteration() - - for _, opt := range opts { - if optDiags := opt(bucket); optDiags.HasErrors() { - diags = append(diags, optDiags...) - } - } - - if bucket.Slug == "" { - diags = append(diags, &hcl.Diagnostic{ - Summary: "Image bucket name required", - Detail: "You must provide an image bucket name for HCP Packer builds. " + - "You can set the HCP_PACKER_BUCKET_NAME environment variable. " + - "For HCL2 templates, the registry either uses the name of your " + - "template's build block, or you can set the bucket_name argument " + - "in an hcp_packer_registry block.", - Severity: hcl.DiagError, - }) - } - - err := bucket.Iteration.Initialize(registry.IterationOptions{ - TemplateBaseDir: templateDir, - }) - - if err != nil { - diags = append(diags, &hcl.Diagnostic{ - Summary: "Iteration initialization failed", - Detail: fmt.Sprintf("Initialization of the iteration failed with "+ - "the following error message: %s", err), - Severity: hcl.DiagError, - }) - } - return bucket, diags -} - -func withPackerEnvConfiguration(bucket *registry.Bucket) hcl.Diagnostics { - // Add default values for Packer settings configured via EnvVars. - // TODO look to break this up to be more explicit on what is loaded here. - bucket.LoadDefaultSettingsFromEnv() - - return nil + return &hclOrchestrator{ + configuration: config, + bucket: bucket, + }, nil } func imageValueToDSOutput(imageVal map[string]cty.Value) imgds.DatasourceOutput { diff --git a/internal/hcp/json.go b/internal/hcp/json.go new file mode 100644 index 000000000..389cfcc92 --- /dev/null +++ b/internal/hcp/json.go @@ -0,0 +1,83 @@ +package hcp + +import ( + "context" + "path/filepath" + + "github.com/hashicorp/hcl/v2" + sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer/internal/registry" + "github.com/hashicorp/packer/internal/registry/env" + "github.com/hashicorp/packer/packer" +) + +// jsonOrchestrator is a HCP handler made to process legacy JSON templates +type jsonOrchestrator struct { + configuration *packer.Core + bucket *registry.Bucket +} + +func newJSONOrchestrator(config *packer.Core) (Orchestrator, hcl.Diagnostics) { + if env.IsHCPDisabled() || + (!env.HasPackerRegistryBucket() && !env.IsHCPExplicitelyEnabled()) { + return newNoopHandler(), nil + } + + bucket, diags := createConfiguredBucket( + filepath.Dir(config.Template.Path), + withPackerEnvConfiguration, + ) + + if diags.HasErrors() { + return nil, diags + } + + for _, b := range config.Template.Builders { + // Get all builds slated within config ignoring any only or exclude flags. + bucket.RegisterBuildForComponent(packer.HCPName(b)) + } + + return &jsonOrchestrator{ + configuration: config, + bucket: bucket, + }, nil +} + +// PopulateIteration creates the metadata on HCP for a build +func (h *jsonOrchestrator) PopulateIteration(ctx context.Context) error { + for _, b := range h.configuration.Template.Builders { + // Get all builds slated within config ignoring any only or exclude flags. + h.bucket.RegisterBuildForComponent(b.Name) + } + + err := h.bucket.Validate() + if err != nil { + return err + } + err = h.bucket.Initialize(ctx) + if err != nil { + return err + } + + err = h.bucket.PopulateIteration(ctx) + if err != nil { + return err + } + + return nil +} + +// BuildStart is invoked when one build for the configuration is starting to be processed +func (h *jsonOrchestrator) BuildStart(ctx context.Context, buildName string) error { + return h.bucket.BuildStart(ctx, buildName) +} + +// BuildDone is invoked when one build for the configuration has finished +func (h *jsonOrchestrator) BuildDone( + ctx context.Context, + buildName string, + artifacts []sdkpacker.Artifact, + buildErr error, +) ([]sdkpacker.Artifact, error) { + return h.bucket.BuildDone(ctx, buildName, artifacts, buildErr) +} diff --git a/internal/hcp/noop.go b/internal/hcp/noop.go new file mode 100644 index 000000000..076a10170 --- /dev/null +++ b/internal/hcp/noop.go @@ -0,0 +1,31 @@ +package hcp + +import ( + "context" + + sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer" +) + +// noopOrchestrator is a special handler that does nothing +type noopOrchestrator struct{} + +func newNoopHandler() Orchestrator { + return noopOrchestrator{} +} + +func (h noopOrchestrator) PopulateIteration(context.Context) error { + return nil +} + +func (h noopOrchestrator) BuildStart(context.Context, string) error { + return nil +} + +func (h noopOrchestrator) BuildDone( + ctx context.Context, + buildName string, + artifacts []sdkpacker.Artifact, + buildErr error, +) ([]sdkpacker.Artifact, error) { + return artifacts, nil +} diff --git a/internal/hcp/orchestrator.go b/internal/hcp/orchestrator.go new file mode 100644 index 000000000..a907f2d2b --- /dev/null +++ b/internal/hcp/orchestrator.go @@ -0,0 +1,34 @@ +package hcp + +import ( + "context" + + "github.com/hashicorp/hcl/v2" + sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer" + "github.com/hashicorp/packer/hcl2template" + "github.com/hashicorp/packer/packer" +) + +// Orchestrator is an entity capable to orchestrate a Packer build and upload metadata to HCP +type Orchestrator interface { + PopulateIteration(context.Context) error + BuildStart(context.Context, string) error + BuildDone(ctx context.Context, buildName string, artifacts []sdkpacker.Artifact, buildErr error) ([]sdkpacker.Artifact, error) +} + +// GetOrchestrator instanciates the appropriate handler for the configuration type given as parameter. +// +// If no HCP-related data is present, it will be a NoopHandler. +func GetOrchestrator(cfg packer.Handler) (Orchestrator, hcl.Diagnostics) { + var handler Orchestrator + var err hcl.Diagnostics + + switch cfg := cfg.(type) { + case *hcl2template.PackerConfig: + handler, err = newHCLOrchestrator(cfg) + case *packer.Core: + handler, err = newJSONOrchestrator(cfg) + } + + return handler, err +} diff --git a/internal/registry/types.bucket.go b/internal/registry/types.bucket.go index ecb0cad29..5654e85b4 100644 --- a/internal/registry/types.bucket.go +++ b/internal/registry/types.bucket.go @@ -524,6 +524,7 @@ func (b *Bucket) BuildDone( 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 @@ -547,13 +548,17 @@ func (b *Bucket) BuildDone( ErrorUnused: false, }) if err != nil { - return artifacts, fmt.Errorf("failed to create decoder for HCP Packer registry image: %w", err) + 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) + 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...) diff --git a/packer/core.go b/packer/core.go index 47cfe45cf..40b6560ed 100644 --- a/packer/core.go +++ b/packer/core.go @@ -14,11 +14,11 @@ import ( "github.com/google/go-cmp/cmp" multierror "github.com/hashicorp/go-multierror" version "github.com/hashicorp/go-version" - "github.com/hashicorp/hcl/v2" + hcl "github.com/hashicorp/hcl/v2" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - packerregistry "github.com/hashicorp/packer/internal/registry" + plugingetter "github.com/hashicorp/packer/packer/plugin-getter" packerversion "github.com/hashicorp/packer/version" ) @@ -27,8 +27,6 @@ import ( type Core struct { Template *template.Template - Bucket *packerregistry.Bucket - components ComponentFinder variables map[string]string builds map[string]*template.Builder @@ -131,7 +129,20 @@ func NewCore(c *CoreConfig) *Core { return core } -func (core *Core) Initialize() error { +func (c *Core) Initialize(_ InitializeOptions) hcl.Diagnostics { + err := c.initialize() + if err != nil { + return hcl.Diagnostics{ + &hcl.Diagnostic{ + Detail: err.Error(), + Severity: hcl.DiagError, + }, + } + } + return nil +} + +func (core *Core) initialize() error { if err := core.validate(); err != nil { return err } @@ -155,9 +166,20 @@ func (core *Core) Initialize() error { core.builds[v] = b } + return nil } +func (c *Core) PluginRequirements() (plugingetter.Requirements, hcl.Diagnostics) { + return nil, hcl.Diagnostics{ + &hcl.Diagnostic{ + Summary: "Packer plugins currently only works with HCL2 configuration templates", + Detail: "Please manually install plugins with the plugins command or use a HCL2 configuration that will do that for you.", + Severity: hcl.DiagError, + }, + } +} + // BuildNames returns the builds that are available in this configured core. func (c *Core) BuildNames(only, except []string) []string { @@ -889,9 +911,3 @@ func (c *Core) init() error { return nil } - -/// GetRegistryBucket returns a configured bucket that can be used for -// publishing build image artifacts to some HCP Packer Registry. -func (c *Core) GetRegistryBucket() *packerregistry.Bucket { - return c.Bucket -} diff --git a/packer/core_test.go b/packer/core_test.go index a8dd6c140..309e54755 100644 --- a/packer/core_test.go +++ b/packer/core_test.go @@ -43,9 +43,9 @@ func TestCoreBuildNames(t *testing.T) { Template: tpl, Variables: tc.Vars, }) - err = core.Initialize() - if err != nil { - t.Fatalf("err: %s\n\n%s", tc.File, err) + diags := core.Initialize(InitializeOptions{}) + if diags.HasErrors() { + t.Fatalf("err: %s\n\n%s", tc.File, diags) } names := core.BuildNames(nil, nil) @@ -493,9 +493,9 @@ func TestCoreValidate(t *testing.T) { Variables: tc.Vars, Version: "1.0.0", }) - err = core.Initialize() + diags := core.Initialize(InitializeOptions{}) - if (err != nil) != tc.Err { + if diags.HasErrors() != tc.Err { t.Fatalf("err: %s\n\n%s", tc.File, err) } } @@ -541,13 +541,13 @@ func TestCore_InterpolateUserVars(t *testing.T) { Template: tpl, Version: "1.0.0", }) - err = ccf.Initialize() + diags := ccf.Initialize(InitializeOptions{}) - if (err != nil) != tc.Err { + if diags.HasErrors() != tc.Err { if tc.Err == false { - t.Fatalf("Error interpolating %s: Expected no error, but got: %s", tc.File, err) + t.Fatalf("Error interpolating %s: Expected no error, but got: %s", tc.File, diags) } else { - t.Fatalf("Error interpolating %s: Expected an error, but got: %s", tc.File, err) + t.Fatalf("Error interpolating %s: Expected an error, but got: %s", tc.File, diags) } } @@ -614,10 +614,10 @@ func TestCore_InterpolateUserVars_VarFile(t *testing.T) { Version: "1.0.0", Variables: tc.Variables, }) - err = ccf.Initialize() + diags := ccf.Initialize(InitializeOptions{}) - if (err != nil) != tc.Err { - t.Fatalf("err: %s\n\n%s", tc.File, err) + if diags.HasErrors() != tc.Err { + t.Fatalf("err: %s\n\n%s", tc.File, diags) } if !tc.Err { for k, v := range ccf.variables { @@ -674,10 +674,10 @@ func TestSensitiveVars(t *testing.T) { Variables: tc.Vars, Version: "1.0.0", }) - err = ccf.Initialize() + diags := ccf.Initialize(InitializeOptions{}) - if (err != nil) != tc.Err { - t.Fatalf("err: %s\n\n%s", tc.File, err) + if diags.HasErrors() != tc.Err { + t.Fatalf("err: %s\n\n%s", tc.File, diags) } // Check that filter correctly manipulates strings: filtered := packersdk.LogSecretFilter.FilterString("the foo jumped over the bar_extra_sensitive_probably_a_password") @@ -756,7 +756,7 @@ func TestEnvAndFileVars(t *testing.T) { "final_var": "{{user `env_1`}}/{{user `env_2`}}/{{user `env_4`}}{{user `env_3`}}-{{user `var_1`}}/vmware/{{user `var_2`}}.vmx", }, }) - err = ccf.Initialize() + diags := ccf.Initialize(InitializeOptions{}) expected := map[string]string{ "var_1": "partyparrot", @@ -767,8 +767,8 @@ func TestEnvAndFileVars(t *testing.T) { "env_3": "/path/to/nowhere", "env_4": "bananas", } - if err != nil { - t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", err) + if diags.HasErrors() { + t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", diags) } for k, v := range ccf.variables { if expected[k] != v { diff --git a/packer/run_interfaces.go b/packer/run_interfaces.go index aa1d69dd0..0eff3fa4c 100644 --- a/packer/run_interfaces.go +++ b/packer/run_interfaces.go @@ -1,9 +1,8 @@ package packer import ( - "github.com/hashicorp/hcl/v2" + hcl "github.com/hashicorp/hcl/v2" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - packerregistry "github.com/hashicorp/packer/internal/registry" plugingetter "github.com/hashicorp/packer/packer/plugin-getter" ) @@ -51,14 +50,6 @@ type Handler interface { BuildGetter ConfigFixer ConfigInspector - HCPHandler -} - -// The HCPHandler handles Packer things needed for communicating with a HCP Packer Registry. -type HCPHandler interface { - // ConfiguredArtifactMetadataPublisher returns a configured Bucket that can be used to publish - // build artifacts to the said image bucket. - ConfiguredArtifactMetadataPublisher() (*packerregistry.Bucket, hcl.Diagnostics) } //go:generate enumer -type FixConfigMode diff --git a/packer/testing.go b/packer/testing.go index 407802971..dcdcf2a30 100644 --- a/packer/testing.go +++ b/packer/testing.go @@ -25,7 +25,7 @@ func TestCoreConfig(t *testing.T) *CoreConfig { func TestCore(t *testing.T, c *CoreConfig) *Core { core := NewCore(c) - err := core.Initialize() + err := core.Initialize(InitializeOptions{}) if err != nil { t.Fatalf("err: %s", err) }