mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-05 06:42:30 -04:00
tmp: move HCP logic to unwrap builds/post
This commit is contained in:
parent
f0d0a0e6c5
commit
f3e4c2c3bb
9 changed files with 182 additions and 515 deletions
|
|
@ -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: ®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,
|
||||
|
|
|
|||
|
|
@ -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…
Reference in a new issue