mirror of https://github.com/hashicorp/packer
Migrate to internal Registry tests (#11806)
* Implement HPATS in Nightly build, delete registry par test * Update .github/workflows/acceptance-test.yml * add workflow-dispatchpull/11807/head
parent
adc130a73e
commit
961c1d7046
@ -1,310 +0,0 @@
|
||||
package acctest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
structenv "github.com/caarlos0/env/v6"
|
||||
packer_service "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
|
||||
"github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
|
||||
sharedmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models"
|
||||
"github.com/hashicorp/packer/acctest"
|
||||
"github.com/hashicorp/packer/internal/registry"
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
type hcpConf struct {
|
||||
OrgId string `env:"HCP_ORG_ID"`
|
||||
ProjectId string `env:"HCP_PROJECT_ID"`
|
||||
ApiHost string `env:"HCP_API_HOST"`
|
||||
AuthUrl string `env:"HCP_AUTH_URL"`
|
||||
ClientId string `env:"HCP_CLIENT_ID"`
|
||||
ClientSecret string `env:"HCP_CLIENT_SECRET"`
|
||||
UserAgent string `env:"HCP_CLIENT_USER_AGENT" envDefault:"packer-par-acc-test"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
*registry.Client
|
||||
Loc *sharedmodels.HashicorpCloudLocationLocation
|
||||
T *testing.T
|
||||
}
|
||||
|
||||
func NewTestConfig(t *testing.T) (*Config, error) {
|
||||
checkEnvVars(t)
|
||||
cfg := hcpConf{}
|
||||
if err := structenv.Parse(&cfg); err != nil {
|
||||
t.Errorf("%+v\n", err)
|
||||
}
|
||||
cli, err := registry.NewClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Config{
|
||||
Client: cli,
|
||||
Loc: &sharedmodels.HashicorpCloudLocationLocation{
|
||||
OrganizationID: cli.OrganizationID,
|
||||
ProjectID: cli.ProjectID,
|
||||
},
|
||||
T: t,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func checkEnvVars(t *testing.T) {
|
||||
t.Helper()
|
||||
if os.Getenv(acctest.TestEnvVar) == "" {
|
||||
t.Skip(fmt.Sprintf(
|
||||
"Acceptance tests skipped unless env '%s' set",
|
||||
acctest.TestEnvVar))
|
||||
return
|
||||
}
|
||||
if os.Getenv("HCP_CLIENT_ID") == "" {
|
||||
t.Fatal("HCP_CLIENT_ID must be set for acceptance tests")
|
||||
}
|
||||
if os.Getenv("HCP_CLIENT_SECRET") == "" {
|
||||
t.Fatal("HCP_CLIENT_SECRET must be set for acceptance tests")
|
||||
}
|
||||
}
|
||||
|
||||
// GetIterationByID is a helper to validate that the id for a given bucketSlug returns a valid Iteration ID.
|
||||
func (cfg *Config) GetIterationByID(
|
||||
bucketSlug,
|
||||
id string,
|
||||
) string {
|
||||
cfg.T.Helper()
|
||||
|
||||
getItParams := packer_service.NewPackerServiceGetIterationParams()
|
||||
getItParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
getItParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
getItParams.BucketSlug = bucketSlug
|
||||
getItParams.IterationID = &id
|
||||
|
||||
ok, err := cfg.Packer.PackerServiceGetIteration(getItParams, nil)
|
||||
if err != nil {
|
||||
cfg.T.Fatal(err)
|
||||
}
|
||||
return ok.Payload.Iteration.ID
|
||||
}
|
||||
|
||||
// UpsertIteration creates a new iteration if it does not already exists.
|
||||
func (cfg *Config) UpsertIteration(
|
||||
bucketSlug,
|
||||
fingerprint string,
|
||||
) string {
|
||||
cfg.T.Helper()
|
||||
|
||||
_, err := cfg.CreateIteration(context.Background(), bucketSlug, fingerprint)
|
||||
if err == nil {
|
||||
return cfg.GetIterationIDFromFingerPrint(bucketSlug, fingerprint)
|
||||
}
|
||||
if err, ok := err.(*packer_service.PackerServiceCreateIterationDefault); ok {
|
||||
switch err.Code() {
|
||||
case int(codes.AlreadyExists), http.StatusConflict:
|
||||
// all good here !
|
||||
return cfg.GetIterationIDFromFingerPrint(bucketSlug, fingerprint)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.T.Fatalf("unexpected CreateIteration error, expected nil or 409. Got %v", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// MarkIterationAsDone sends an update request to mark an existing iteration as complete.
|
||||
func (cfg *Config) MarkIterationAsDone(
|
||||
bucketSlug,
|
||||
iterID string,
|
||||
) {
|
||||
cfg.T.Helper()
|
||||
|
||||
updateItParams := packer_service.NewPackerServiceUpdateIterationParams()
|
||||
updateItParams.Body = &models.HashicorpCloudPackerUpdateIterationRequest{
|
||||
BucketSlug: bucketSlug,
|
||||
IterationID: iterID,
|
||||
Complete: true,
|
||||
}
|
||||
updateItParams.IterationID = iterID
|
||||
updateItParams.LocationOrganizationID = cfg.OrganizationID
|
||||
updateItParams.LocationProjectID = cfg.ProjectID
|
||||
|
||||
_, err := cfg.Packer.PackerServiceUpdateIteration(updateItParams, nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
cfg.T.Errorf("unexpected UpdateIteration error: %v", err)
|
||||
}
|
||||
|
||||
// GetIterationIDFromFingerPrint returns an iteration ID given its unique
|
||||
// fingerprincfg.t.
|
||||
func (cfg *Config) GetIterationIDFromFingerPrint(
|
||||
bucketSlug,
|
||||
fingerprint string,
|
||||
) string {
|
||||
cfg.T.Helper()
|
||||
|
||||
getItParams := packer_service.NewPackerServiceGetIterationParams()
|
||||
getItParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
getItParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
getItParams.BucketSlug = bucketSlug
|
||||
getItParams.Fingerprint = &fingerprint
|
||||
|
||||
ok, err := cfg.Packer.PackerServiceGetIteration(getItParams, nil)
|
||||
if err != nil {
|
||||
cfg.T.Fatal(err)
|
||||
}
|
||||
return ok.Payload.Iteration.ID
|
||||
}
|
||||
|
||||
// UpsertBuild creates a new build for iteration if it does not already exists.
|
||||
func (cfg *Config) UpsertBuild(
|
||||
bucketSlug,
|
||||
iterationFingerprint,
|
||||
runUUID,
|
||||
iterationID,
|
||||
cloudProvider,
|
||||
componentType,
|
||||
region string,
|
||||
imageIDs []string,
|
||||
) {
|
||||
|
||||
build, err := cfg.CreateBuild(context.Background(),
|
||||
bucketSlug,
|
||||
runUUID,
|
||||
iterationID,
|
||||
iterationFingerprint,
|
||||
componentType,
|
||||
models.HashicorpCloudPackerBuildStatusUNSET,
|
||||
)
|
||||
if err, ok := err.(*packer_service.PackerServiceCreateBuildDefault); ok {
|
||||
switch err.Code() {
|
||||
case int(codes.Aborted), http.StatusConflict:
|
||||
// all good here !
|
||||
return
|
||||
default:
|
||||
cfg.T.Fatalf("couldn't create build: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if build == nil {
|
||||
cfg.T.Errorf("unexpected CreateBuild error, expected non nil build response. Got %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Iterations are currently only assigned an incremental version when publishing image metadata on update.
|
||||
// Incremental versions are a requirement for assigning the channel.
|
||||
updateBuildParams := packer_service.NewPackerServiceUpdateBuildParams()
|
||||
updateBuildParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
updateBuildParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
updateBuildParams.BuildID = build.Payload.Build.ID
|
||||
updateBuildParams.Body = &models.HashicorpCloudPackerUpdateBuildRequest{
|
||||
Updates: &models.HashicorpCloudPackerBuildUpdates{
|
||||
CloudProvider: cloudProvider,
|
||||
Status: models.HashicorpCloudPackerBuildStatusDONE,
|
||||
},
|
||||
}
|
||||
for _, imageID := range imageIDs {
|
||||
updateBuildParams.Body.Updates.Images = append(updateBuildParams.Body.Updates.Images, &models.HashicorpCloudPackerImageCreateBody{
|
||||
ImageID: imageID,
|
||||
Region: region,
|
||||
})
|
||||
}
|
||||
_, err = cfg.Packer.PackerServiceUpdateBuild(updateBuildParams, nil)
|
||||
if err, ok := err.(*packer_service.PackerServiceUpdateBuildDefault); ok {
|
||||
cfg.T.Errorf("unexpected UpdateBuild error, expected nil. Got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *Config) UpsertChannel(
|
||||
bucketSlug,
|
||||
channelSlug,
|
||||
iterationID string,
|
||||
) {
|
||||
cfg.T.Helper()
|
||||
|
||||
createChParams := packer_service.NewPackerServiceCreateChannelParams()
|
||||
createChParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
createChParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
createChParams.BucketSlug = bucketSlug
|
||||
createChParams.Body = &models.HashicorpCloudPackerCreateChannelRequest{
|
||||
Slug: channelSlug,
|
||||
IncrementalVersion: 1,
|
||||
IterationID: iterationID,
|
||||
}
|
||||
|
||||
_, err := cfg.Packer.PackerServiceCreateChannel(createChParams, nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if err, ok := err.(*packer_service.PackerServiceCreateChannelDefault); ok {
|
||||
switch err.Code() {
|
||||
case int(codes.Aborted), http.StatusConflict:
|
||||
// all good here !
|
||||
cfg.UpdateChannel(bucketSlug, channelSlug)
|
||||
return
|
||||
}
|
||||
}
|
||||
cfg.T.Errorf("unexpected CreateChannel error, expected nil. Got %v", err)
|
||||
}
|
||||
|
||||
func (cfg *Config) UpdateChannel(
|
||||
bucketSlug,
|
||||
channelSlug string,
|
||||
) {
|
||||
cfg.T.Helper()
|
||||
|
||||
updateChParams := packer_service.NewPackerServiceUpdateChannelParams()
|
||||
updateChParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
updateChParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
updateChParams.BucketSlug = bucketSlug
|
||||
updateChParams.Slug = channelSlug
|
||||
updateChParams.Body = &models.HashicorpCloudPackerUpdateChannelRequest{
|
||||
IncrementalVersion: 1,
|
||||
}
|
||||
|
||||
_, err := cfg.Packer.PackerServiceUpdateChannel(updateChParams, nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
cfg.T.Errorf("unexpected UpdateChannel error, expected nil. Got %v", err)
|
||||
}
|
||||
|
||||
func (cfg *Config) DeleteIteration(
|
||||
bucketSlug,
|
||||
iterationID string,
|
||||
) {
|
||||
cfg.T.Helper()
|
||||
|
||||
deleteItParams := packer_service.NewPackerServiceDeleteIterationParams()
|
||||
deleteItParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
deleteItParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
deleteItParams.BucketSlug = &bucketSlug
|
||||
deleteItParams.IterationID = iterationID
|
||||
|
||||
_, err := cfg.Packer.PackerServiceDeleteIteration(deleteItParams, nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
cfg.T.Errorf("unexpected DeleteIteration error, expected nil. Got %v", err)
|
||||
}
|
||||
|
||||
func (cfg *Config) DeleteChannel(
|
||||
bucketSlug,
|
||||
channelSlug string,
|
||||
) {
|
||||
cfg.T.Helper()
|
||||
|
||||
deleteChParams := packer_service.NewPackerServiceDeleteChannelParams()
|
||||
deleteChParams.LocationOrganizationID = cfg.Loc.OrganizationID
|
||||
deleteChParams.LocationProjectID = cfg.Loc.ProjectID
|
||||
deleteChParams.BucketSlug = bucketSlug
|
||||
deleteChParams.Slug = channelSlug
|
||||
|
||||
_, err := cfg.Packer.PackerServiceDeleteChannel(deleteChParams, nil)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
cfg.T.Errorf("unexpected DeleteChannel error, expected nil. Got %v", err)
|
||||
}
|
||||
@ -1,186 +0,0 @@
|
||||
package acctest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/command"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
const (
|
||||
channel = "acc"
|
||||
)
|
||||
|
||||
func TestAcc_PAR_service_create_and_datasource(t *testing.T) {
|
||||
runUUID := "11118ff1-a860-44a3-a669-a4f1b4a12688"
|
||||
os.Setenv("PACKER_RUN_UUID", runUUID)
|
||||
|
||||
checkEnvVars(t)
|
||||
const tmpBucket = "pkr-acctest-temp-1"
|
||||
|
||||
// allow other tests to go.
|
||||
t.Parallel()
|
||||
|
||||
cfg, err := NewTestConfig(t)
|
||||
if err != nil {
|
||||
t.Fatalf("NewParConfig: %v", err)
|
||||
}
|
||||
|
||||
_, _ = cfg.DeleteBucket(context.Background(), tmpBucket)
|
||||
defer func() {
|
||||
_, err := cfg.DeleteBucket(context.Background(), tmpBucket) // Hopefully everything else is deleted too
|
||||
if err != nil {
|
||||
t.Fatalf("failed to delete bucket: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// create our bucket, this should fail if the bucket already exists
|
||||
_, err = cfg.CreateBucket(context.Background(), tmpBucket, "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateBucket: %v", err)
|
||||
}
|
||||
|
||||
// insert tons of iteration
|
||||
iterations := []map[string]map[string][]string{
|
||||
{
|
||||
"aws": {"us-west-1": {"ami:something_1", "ami:other_thing"}},
|
||||
"gcp": {"us-west-1": {"gcp_something_1", "gcpp"}},
|
||||
"azure": {"us-west-1": {"azure_something_1", "azaz"}},
|
||||
"vmware-iso": {"": {"iso_something_1", "vmvmvm"}},
|
||||
},
|
||||
{
|
||||
"aws": {"us-west-1": {"ami:something_2", "ami:other_thing"}},
|
||||
"gcp": {"us-west-1": {"gcp_something_2", "gcpp"}},
|
||||
"azure": {"us-west-1": {"azure_something_2", "azaz"}},
|
||||
"vmware-iso": {"": {"iso_something_2", "vmvmvm"}},
|
||||
},
|
||||
{
|
||||
"aws": {"us-west-1": {"ami:something_3"}},
|
||||
"gcp": {"us-west-1": {"gcp_something_3", "gcpp"}},
|
||||
"azure": {"us-west-1": {"azure_something_3", "azaz"}},
|
||||
"vmware-iso": {"": {"iso_something_3", "vmvmvm"}},
|
||||
},
|
||||
}
|
||||
|
||||
lastIterationID := ""
|
||||
for i, builds := range iterations {
|
||||
iterationFingerprint := strconv.Itoa(i)
|
||||
iterationID := cfg.UpsertIteration(tmpBucket, iterationFingerprint)
|
||||
|
||||
for cloud, builds := range builds {
|
||||
for region, imageIDs := range builds {
|
||||
cfg.UpsertBuild(
|
||||
tmpBucket,
|
||||
iterationFingerprint,
|
||||
runUUID,
|
||||
iterationID,
|
||||
cloud,
|
||||
cloud,
|
||||
region,
|
||||
imageIDs,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond)
|
||||
lastIterationID = iterationID
|
||||
}
|
||||
|
||||
if cfg.GetIterationByID(tmpBucket, lastIterationID) != lastIterationID {
|
||||
t.Fatal("that should not be possible")
|
||||
}
|
||||
|
||||
cfg.UpsertChannel(tmpBucket, channel, lastIterationID)
|
||||
|
||||
// now, let's try getting the datasource
|
||||
|
||||
meta := command.TestMetaFile(t)
|
||||
ui := meta.Ui.(*packersdk.BasicUi)
|
||||
c := &command.BuildCommand{
|
||||
Meta: meta,
|
||||
}
|
||||
|
||||
code := c.Run([]string{"./test-fixtures/ds.pkr.hcl"})
|
||||
outW := ui.Writer.(*bytes.Buffer)
|
||||
errW := ui.ErrorWriter.(*bytes.Buffer)
|
||||
if code != 0 {
|
||||
t.Fatalf(
|
||||
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
outW.String(),
|
||||
errW.String())
|
||||
}
|
||||
|
||||
if !strings.Contains(outW.String(), "the artifact id is: ami:something_3, yup yup") {
|
||||
t.Fatal("data source not found ?")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAcc_PAR_pkr_build(t *testing.T) {
|
||||
|
||||
runUUID := "11118ff1-a860-44a3-a669-a4f1b4a12688"
|
||||
os.Setenv("PACKER_RUN_UUID", runUUID)
|
||||
|
||||
checkEnvVars(t)
|
||||
const tmpBucket = "pkr-acctest-temp-2"
|
||||
|
||||
// allow other tests to go.
|
||||
t.Parallel()
|
||||
|
||||
cfg, err := NewTestConfig(t)
|
||||
if err != nil {
|
||||
t.Fatalf("NewParConfig: %v", err)
|
||||
}
|
||||
|
||||
_, _ = cfg.DeleteBucket(context.Background(), tmpBucket)
|
||||
defer func() {
|
||||
_, err := cfg.DeleteBucket(context.Background(), tmpBucket) // Hopefully everything else is deleted too
|
||||
if err != nil {
|
||||
t.Fatalf("failed to delete bucket: %v", err)
|
||||
}
|
||||
}()
|
||||
// create our bucket, this should fail if the bucket already exists
|
||||
_, err = cfg.CreateBucket(context.Background(), tmpBucket, "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateBucket: %v", err)
|
||||
}
|
||||
|
||||
// now, let's try building something
|
||||
|
||||
meta := command.TestMetaFile(t)
|
||||
ui := meta.Ui.(*packersdk.BasicUi)
|
||||
c := &command.BuildCommand{
|
||||
Meta: meta,
|
||||
}
|
||||
|
||||
code := c.Run([]string{"./test-fixtures/build.pkr.hcl"})
|
||||
outW := ui.Writer.(*bytes.Buffer)
|
||||
errW := ui.ErrorWriter.(*bytes.Buffer)
|
||||
if code != 0 {
|
||||
t.Fatalf(
|
||||
"Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
outW.String(),
|
||||
errW.String())
|
||||
}
|
||||
|
||||
// extract id from output
|
||||
re := regexp.MustCompile(`(?m)^.*packer/` + tmpBucket + `/iterations/(\S*)`)
|
||||
match := re.FindStringSubmatch(outW.String())
|
||||
if len(match) != 2 {
|
||||
t.Fatalf("Could not extract ID from output.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
|
||||
outW.String(),
|
||||
errW.String())
|
||||
}
|
||||
iterationID := match[1]
|
||||
|
||||
if foundID := cfg.GetIterationByID(tmpBucket, iterationID); foundID != iterationID {
|
||||
t.Fatalf("could not find iteration back in service: expected %q, found %q", iterationID, foundID)
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
|
||||
variable "bkt" {
|
||||
default = "pkr-acctest-temp-2"
|
||||
}
|
||||
|
||||
source "null" "example" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
hcp_packer_registry {
|
||||
bucket_name = "pkr-acctest-temp-2"
|
||||
description = "blah"
|
||||
|
||||
build_labels = {
|
||||
"foo-version" = "3.4.0"
|
||||
"foo" = "bar"
|
||||
}
|
||||
}
|
||||
|
||||
sources = [
|
||||
"source.null.example"
|
||||
]
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo test"]
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
|
||||
variable "bkt" {
|
||||
default = "pkr-acctest-temp-1"
|
||||
}
|
||||
|
||||
data "hcp-packer-iteration" "acc" {
|
||||
bucket_name = var.bkt
|
||||
channel = "acc"
|
||||
}
|
||||
|
||||
data "hcp-packer-image" "acc-production" {
|
||||
bucket_name = var.bkt
|
||||
iteration_id = data.hcp-packer-iteration.acc.id
|
||||
cloud_provider = "aws"
|
||||
region = "us-west-1"
|
||||
}
|
||||
|
||||
source "null" "example" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
sources = [
|
||||
"source.null.example"
|
||||
]
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo the artifact id is: '${data.hcp-packer-image.acc-production.id}', yup yup"]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue