Migrate to internal Registry tests (#11806)

* Implement HPATS in Nightly build, delete registry par test

* Update .github/workflows/acceptance-test.yml

* add workflow-dispatch
pull/11807/head
Jenna Goldstrich 4 years ago committed by GitHub
parent adc130a73e
commit 961c1d7046
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,6 +9,7 @@ on:
schedule:
# Runs against the default branch every day at midnight
- cron: "0 0 * * *"
workflow-dispatch:
jobs:
get-go-version:
@ -26,7 +27,7 @@ jobs:
echo "::set-output name=go-version::$(cat .go-version)"
acceptance-test:
runs-on: ubuntu-latest
name: Acceptance Test
name: Packer Acceptance Test
needs: get-go-version
env:
# AWS Creds for Assume Role
@ -34,11 +35,6 @@ jobs:
AWS_ACCESS_KEY_ID: ${{ secrets.TESTACC_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.TESTACC_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.TESTACC_AWS_REGION }}
# HCP Creds for Acceptance Tests
HCP_CLIENT_ID: ${{ secrets.HCP_CLIENT_ID }}
HCP_CLIENT_SECRET: ${{ secrets.HCP_CLIENT_SECRET }}
HCP_ORG_ID: ${{ secrets.HCP_ORG_ID }}
HCP_PROJECT_ID: ${{ secrets.HCP_PROJECT_ID }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
@ -58,13 +54,40 @@ jobs:
run: |
mkdir -p /tmp/test-results
make dev
PACKER_ACC=1 gotestsum --format=short-verbose --junitfile /tmp/test-results/gotestsum-report.xml -- -timeout=120m -p 2 $(go list ./... | grep -v inspec | grep -v profitbricks | grep -v oneandone)
# Send a slack notification if either job defined above fails
PACKER_ACC=1 gotestsum --format=short-verbose --junitfile /tmp/test-results/gotestsum-report.xml -- -timeout=120m -p 2 $(go list ./... | grep -v inspec | grep -v profitbricks | grep -v oneandone)
hpats:
runs-on: ubuntu-latest
name: HCP Packer Acceptance Test (HPATS)
needs: get-go-version
env:
# Set HCP credentials
HCP_CLIENT_ID: ${{ secrets.HCP_CLIENT_ID }}
HCP_CLIENT_SECRET: ${{ secrets.HCP_CLIENT_SECRET }}
AUTH0_CLIENT_ID: ${{ secrets.HCP_CLIENT_ID }}
AUTH0_CLIENT_SECRET: ${{ secrets.HCP_CLIENT_SECRET }}
AUTH0_HOST: ${{ secrets.AUTH0_HOST }}
HCP_ORG_ID: ${{ secrets.HCP_ORG_ID }}
HCP_PROJECT_ID: ${{ secrets.HCP_PROJECT_ID }}
HCP_API_HOST: ${{ secrets.HCP_API_HOST }}
HPATS_API_URL: https://${{ secrets.HCP_API_HOST }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: ${{ needs.get-go-version.outputs.go-version }}
- name: Clone HPATS
run: git clone git@github.com:hashicorp/hcp-packer-acceptance-tests.github && cd hcp-packer-acceptance-tests
- name: Set HCP Access Token
run: export HCP_ACCESS_TOKEN=$(make hcp/get-auth0-m2m-access-token)
- name: Run HPATS
run: make test
# Send a slack notification if one of the jobs defined above fails
slack-notify:
needs:
- get-go-version
- acceptance-test
if: always() && (needs.get-go-version.result == 'failure' || needs.acceptance-test.result == 'failure')
- hpats
if: always() && (needs.get-go-version.result == 'failure' || needs.acceptance-test.result == 'failure' || needs.hpats.result == 'failure')
runs-on: ubuntu-latest
steps:
- name: Send slack notification on failure

@ -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…
Cancel
Save