mirror of
https://github.com/hashicorp/packer.git
synced 2026-06-09 00:32:09 -04:00
hcp: fix hcp artifact extraction method
With Packer 1.10.1 we started warning when a build failed to complete because of a potential incompatibility with the builder being used. This led to cases in which the build failed for other reasons, and Packer would still warn of potential incompatibilities, even if the builder was in effect HCP compatible. We attempted to fix this issue by introducing a new error type, and checks when we read the artifacts linked to a build, however this loop would fail when any one of the artifacts is not compatible with HCP Packer, leading to false failures. To avoid this problem, we log incompatibilities to the verbose logger, and only signal the problem if all the artifacts could not be used to upload data to HCP Packer, in which case it's almost certain that if the build succeeded and no artifacts are registered to the build, that all the components used are not compatible with HCP, and should be reported as such to users.
This commit is contained in:
parent
8a1d1e0c88
commit
32f89015fe
2 changed files with 141 additions and 8 deletions
|
|
@ -643,26 +643,34 @@ func (bucket *Bucket) completeBuild(
|
|||
|
||||
state := art.State(packerSDKRegistry.ArtifactStateURI)
|
||||
if state == nil {
|
||||
return packerSDKArtifacts, &NotAHCPArtifactError{
|
||||
fmt.Errorf("The HCP artifact returned by the builder is nil, this is likely because the builder does not support HCP Packer."),
|
||||
}
|
||||
log.Printf("[WARN] - artifact %q returned a nil value for the HCP state, ignoring", art.BuilderId())
|
||||
continue
|
||||
}
|
||||
|
||||
err = decoder.Decode(state)
|
||||
if err != nil {
|
||||
return packerSDKArtifacts, &NotAHCPArtifactError{
|
||||
fmt.Errorf("Failed to obtain HCP Packer compliant artifact: %s", err),
|
||||
}
|
||||
log.Printf("[WARN] - artifact %q failed to be decoded to an HCP artifact, this is probably because it is not compatible: %s", art.BuilderId(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] updating artifacts for build %q", buildName)
|
||||
err = bucket.UpdateArtifactForBuild(buildName, sdkImages...)
|
||||
|
||||
if err != nil {
|
||||
return packerSDKArtifacts, fmt.Errorf("failed to add artifact for %q: %s", buildName, err)
|
||||
}
|
||||
}
|
||||
|
||||
build, err := bucket.Version.Build(buildName)
|
||||
if err != nil {
|
||||
return packerSDKArtifacts, fmt.Errorf(
|
||||
"failed to get build %q from version being built. This is a Packer bug.",
|
||||
buildName)
|
||||
}
|
||||
if len(build.Artifacts) == 0 {
|
||||
return packerSDKArtifacts, &NotAHCPArtifactError{
|
||||
fmt.Errorf("No HCP Packer-compatible artifacts were found for the build"),
|
||||
}
|
||||
}
|
||||
|
||||
parErr := bucket.markBuildComplete(ctx, buildName)
|
||||
if parErr != nil {
|
||||
return packerSDKArtifacts, fmt.Errorf(
|
||||
|
|
|
|||
|
|
@ -5,10 +5,15 @@ package registry
|
|||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2023-01-01/models"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
|
||||
"github.com/hashicorp/packer/hcl2template"
|
||||
hcpPackerAPI "github.com/hashicorp/packer/internal/hcp/api"
|
||||
)
|
||||
|
|
@ -385,3 +390,123 @@ func TestReadFromHCLBuildBlock(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompleteBuild(t *testing.T) {
|
||||
hcpArtifact := &packer.MockArtifact{
|
||||
BuilderIdValue: "builder.test",
|
||||
FilesValue: []string{"file.one"},
|
||||
IdValue: "Test",
|
||||
StateValues: map[string]interface{}{
|
||||
"builder.test": "OK",
|
||||
image.ArtifactStateURI: &image.Image{
|
||||
ImageID: "hcp-test",
|
||||
ProviderName: "none",
|
||||
ProviderRegion: "none",
|
||||
Labels: map[string]string{},
|
||||
SourceImageID: "",
|
||||
},
|
||||
},
|
||||
DestroyCalled: false,
|
||||
StringValue: "",
|
||||
}
|
||||
nonHCPArtifact := &packer.MockArtifact{
|
||||
BuilderIdValue: "builder.test",
|
||||
FilesValue: []string{"file.one"},
|
||||
IdValue: "Test",
|
||||
StateValues: map[string]interface{}{
|
||||
"builder.test": "OK",
|
||||
},
|
||||
DestroyCalled: false,
|
||||
StringValue: "",
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
artifactsToUse []packer.Artifact
|
||||
expectError bool
|
||||
wantNotHCPErr bool
|
||||
}{
|
||||
{
|
||||
"OK - one artifact compatible with HCP",
|
||||
[]packer.Artifact{
|
||||
hcpArtifact,
|
||||
},
|
||||
false, false,
|
||||
},
|
||||
{
|
||||
"Fail - no artifacts",
|
||||
[]packer.Artifact{},
|
||||
true, false,
|
||||
},
|
||||
{
|
||||
"Fail - only non HCP compatible artifacts",
|
||||
[]packer.Artifact{
|
||||
nonHCPArtifact,
|
||||
},
|
||||
true, true,
|
||||
},
|
||||
{
|
||||
"OK - one hcp artifact, one non hcp artifact (order matters)",
|
||||
[]packer.Artifact{
|
||||
hcpArtifact,
|
||||
nonHCPArtifact,
|
||||
},
|
||||
false, false,
|
||||
},
|
||||
{
|
||||
"OK - one non hcp artifact, one hcp artifact (order matters)",
|
||||
[]packer.Artifact{
|
||||
nonHCPArtifact,
|
||||
hcpArtifact,
|
||||
},
|
||||
false, false,
|
||||
},
|
||||
}
|
||||
mockCli := &hcpPackerAPI.Client{
|
||||
Packer: hcpPackerAPI.NewMockPackerClientService(),
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dummyBucket := &Bucket{
|
||||
Name: "test-bucket",
|
||||
Description: "test",
|
||||
Destination: "none",
|
||||
RunningBuilds: map[string]chan struct{}{
|
||||
// Need buffer with 1 cap so we can signal end of
|
||||
// heartbeats in test, otherwise it'll block
|
||||
"test-build": make(chan struct{}, 1),
|
||||
},
|
||||
Version: &Version{
|
||||
ID: "noneID",
|
||||
Fingerprint: "TestFingerprint",
|
||||
RunUUID: "testuuid",
|
||||
builds: sync.Map{},
|
||||
},
|
||||
client: mockCli,
|
||||
}
|
||||
|
||||
dummyBucket.Version.StoreBuild("test-build", &Build{
|
||||
ID: "test-build",
|
||||
Platform: "none",
|
||||
ComponentType: "none",
|
||||
RunUUID: "testuuid",
|
||||
Artifacts: make(map[string]image.Image),
|
||||
Status: models.HashicorpCloudPacker20230101BuildStatusBUILDRUNNING,
|
||||
})
|
||||
|
||||
_, err := dummyBucket.completeBuild(context.Background(), "test-build", tt.artifactsToUse, nil)
|
||||
if err != nil != tt.expectError {
|
||||
t.Errorf("expected %t error; got %t", tt.expectError, err != nil)
|
||||
t.Logf("error was: %s", err)
|
||||
}
|
||||
|
||||
if err != nil && tt.wantNotHCPErr {
|
||||
_, ok := err.(*NotAHCPArtifactError)
|
||||
if !ok {
|
||||
t.Errorf("expected a NotAHCPArtifactError, got a %q", reflect.TypeOf(err).String())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue