Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/go-openapi/runtime v0.26.2
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/hcp-sdk-go v0.98.0
github.com/hashicorp/hcp-sdk-go v0.111.0
github.com/hashicorp/packer-plugin-sdk v0.5.2
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
github.com/mitchellh/mapstructure v1.5.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5R
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hashicorp/hcp-sdk-go v0.98.0 h1:DKLbGJcP9tCR4EBme6npvcigcRuvma6WCyH1ApZuNaU=
github.com/hashicorp/hcp-sdk-go v0.98.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/hcp-sdk-go v0.111.0 h1:tPQs4N3HdwF8NF3gwZQ8b00CJDeuEzmrQh/OsJlhSSs=
github.com/hashicorp/hcp-sdk-go v0.111.0/go.mod h1:vQ4fzdL1AmhIAbCw+4zmFe5Hbpajj3NvRWkJoVuxmAk=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM=
Expand Down
2 changes: 2 additions & 0 deletions post-processor/hcp-vagrant-registry/post-processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"strings"

"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-operation/stable/2020-05-05/client/operation_service"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-vagrant-box-registry/stable/2022-09-30/client"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-vagrant-box-registry/stable/2022-09-30/client/registry_service"
hcpconfig "github.com/hashicorp/hcp-sdk-go/config"
Expand Down Expand Up @@ -285,6 +286,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
state := new(multistep.BasicStateBag)
state.Put("config", &p.config)
state.Put("client", registry_service.New(p.client.Transport, nil))
state.Put("operation-client", operation_service.New(p.client.Transport, nil))
state.Put("artifact", artifact)
state.Put("artifactFilePath", artifact.Files()[0])
state.Put("ui", ui)
Expand Down
172 changes: 171 additions & 1 deletion post-processor/hcp-vagrant-registry/post-processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,69 @@ func TestPostProcessor(t *testing.T) {
wantErr: "Invalid response body",
},
{
desc: "OK - creates box when missing",
desc: "Invalid - creates box when missing - no operation provided",
stack: []stubResponse{
{
Method: "POST",
Path: "/oauth2/token",
Response: `{"access_token": "TEST_TOKEN", "expiry": 0}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64",
StatusCode: 404,
},
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{}`,
StatusCode: 200,
},
},
files: tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox", "architecture": "amd64"}`},
},
wantErr: "Unable to wait for box to become available - Please check HCP Vagrant for box status, and try again.",
},
{
desc: "Invalid - creates box when missing - operation service error",
stack: []stubResponse{
{
Method: "POST",
Path: "/oauth2/token",
Response: `{"access_token": "TEST_TOKEN", "expiry": 0}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64",
StatusCode: 404,
},
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{"operation": {"id": "OP-ID", "location": {"organization_id": "ORG-ID", "project_id": "PROJ-ID"}}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/operation/2020-05-05/organizations/ORG-ID/projects/PROJ-ID/operations/OP-ID/wait",
Response: `{}`,
StatusCode: 500,
},
},
files: tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox", "architecture": "amd64"}`},
},
wantErr: "Unexpected error encountered",
},
{
desc: "Invalid - creates box when missing - no operation data",
stack: []stubResponse{
{
Method: "POST",
Expand All @@ -397,9 +459,117 @@ func TestPostProcessor(t *testing.T) {
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{"operation": {"id": "OP-ID", "location": {"organization_id": "ORG-ID", "project_id": "PROJ-ID"}}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/operation/2020-05-05/organizations/ORG-ID/projects/PROJ-ID/operations/OP-ID/wait",
Response: `{}`,
StatusCode: 200,
},
},
files: tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox", "architecture": "amd64"}`},
},
wantErr: "Unable to check box creation operation status - Please check HCP Vagrant for box status, and try again.",
},
{
desc: "Invalid - creates box when missing - operation reported error",
stack: []stubResponse{
{
Method: "POST",
Path: "/oauth2/token",
Response: `{"access_token": "TEST_TOKEN", "expiry": 0}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64",
StatusCode: 404,
},
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{"operation": {"id": "OP-ID", "location": {"organization_id": "ORG-ID", "project_id": "PROJ-ID"}}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/operation/2020-05-05/organizations/ORG-ID/projects/PROJ-ID/operations/OP-ID/wait",
Response: `{"operation": {"error": {"message": "testing error"}}}`,
StatusCode: 200,
},
},
files: tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox", "architecture": "amd64"}`},
},
wantErr: "Box creation operation reported a failure: testing error - Please try again.",
},
{
desc: "Invalid - creates box when missing - operation not done",
stack: []stubResponse{
{
Method: "POST",
Path: "/oauth2/token",
Response: `{"access_token": "TEST_TOKEN", "expiry": 0}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64",
StatusCode: 404,
},
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{"operation": {"id": "OP-ID", "location": {"organization_id": "ORG-ID", "project_id": "PROJ-ID"}}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/operation/2020-05-05/organizations/ORG-ID/projects/PROJ-ID/operations/OP-ID/wait",
Response: `{"operation": {"state": "RUNNING"}}`,
StatusCode: 200,
},
},
files: tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox", "architecture": "amd64"}`},
},
wantErr: "Timeout exceeded waiting for box to become available - Please verify box creation in HCP Vagrant and try again.",
},
{
desc: "OK - creates box when missing",
stack: []stubResponse{
{
Method: "POST",
Path: "/oauth2/token",
Response: `{"access_token": "TEST_TOKEN", "expiry": 0}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64",
StatusCode: 404,
},
{
Method: "POST",
Path: "/vagrant/2022-09-30/registry/hashicorp/boxes",
Response: `{"operation": {"id": "OP-ID", "location": {"organization_id": "ORG-ID", "project_id": "PROJ-ID"}}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/operation/2020-05-05/organizations/ORG-ID/projects/PROJ-ID/operations/OP-ID/wait",
Response: `{"operation": {"state": "DONE"}}`,
StatusCode: 200,
},
{
Method: "GET",
Path: "/vagrant/2022-09-30/registry/hashicorp/box/precise64/version/0.5",
Expand Down
4 changes: 4 additions & 0 deletions post-processor/hcp-vagrant-registry/step_confirm_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import (

"github.com/hashicorp/hcp-sdk-go/clients/cloud-vagrant-box-registry/stable/2022-09-30/client/registry_service"
"github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/packer"
)

type stepConfirmUpload struct{}

func (s *stepConfirmUpload) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*registry_service.Client)
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)

if config.NoDirectUpload {
return multistep.ActionContinue
Expand All @@ -25,6 +27,8 @@ func (s *stepConfirmUpload) Run(ctx context.Context, state multistep.StateBag) m
archName := state.Get("architecture").(string)
object := state.Get("upload-object").(string)

ui.Say("Completing box upload...")

_, err := client.CompleteDirectUploadBox(
&registry_service.CompleteDirectUploadBoxParams{
Context: ctx,
Expand Down
50 changes: 48 additions & 2 deletions post-processor/hcp-vagrant-registry/step_create_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"context"
"fmt"

"github.com/hashicorp/hcp-sdk-go/clients/cloud-operation/stable/2020-05-05/client/operation_service"
shared_models "github.com/hashicorp/hcp-sdk-go/clients/cloud-shared/v1/models"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-vagrant-box-registry/stable/2022-09-30/client/registry_service"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-vagrant-box-registry/stable/2022-09-30/models"
"github.com/hashicorp/packer-plugin-sdk/multistep"
Expand All @@ -15,6 +17,8 @@ import (

type stepCreateBox struct{}

var BOX_CREATE_TIMEOUT = "60s"

func (s *stepCreateBox) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*registry_service.Client)
ui := state.Get("ui").(packer.Ui)
Expand Down Expand Up @@ -45,7 +49,7 @@ func (s *stepCreateBox) Run(ctx context.Context, state multistep.StateBag) multi
}

// Create the box
_, err = client.CreateBox(
cresp, err := client.CreateBox(
&registry_service.CreateBoxParams{
Context: ctx,
Registry: config.registry,
Expand All @@ -62,11 +66,53 @@ func (s *stepCreateBox) Run(ctx context.Context, state multistep.StateBag) multi
}

if errMsg, ok := errorResponseMsg(err); ok {
state.Put("error", fmt.Errorf("Failure creating new box: %s", errMsg))
state.Put("error", fmt.Errorf("Failure creating new box: %s - Please try again.", errMsg))
return multistep.ActionHalt
}

ui.Say(fmt.Sprintf("Created new box: %s", config.Tag))
if cresp.Payload == nil || cresp.Payload.Operation == nil {
state.Put("error", fmt.Errorf("Unable to wait for box to become available - Please check HCP Vagrant for box status, and try again."))
return multistep.ActionHalt
}

ui.Say("Waiting for box to become available...")
op := cresp.Payload.Operation

operationClient := state.Get("operation-client").(operation_service.ClientService)
waitReq := &operation_service.WaitParams{
ID: op.ID,
LocationOrganizationID: op.Location.OrganizationID,
LocationProjectID: op.Location.ProjectID,
Timeout: &BOX_CREATE_TIMEOUT,
Context: ctx,
}

wresp, err := operationClient.Wait(waitReq, nil)
if isErrorUnexpected(err, state) {
return multistep.ActionHalt
}

if errMsg, ok := errorResponseMsg(err); ok {
state.Put("error", fmt.Errorf("Unexpected failure waiting for box to become available: %s - Please try again.", errMsg))
return multistep.ActionHalt
}

if wresp.Payload == nil || wresp.Payload.Operation == nil {
state.Put("error", fmt.Errorf("Unable to check box creation operation status - Please check HCP Vagrant for box status, and try again."))
return multistep.ActionHalt
}

operation := wresp.Payload.Operation
if operation.Error != nil {
state.Put("error", fmt.Errorf("Box creation operation reported a failure: %s - Please try again.", operation.Error.Message))
return multistep.ActionHalt
}

if operation.State == nil || *operation.State != shared_models.HashicorpCloudOperationOperationStateDONE {
state.Put("error", fmt.Errorf("Timeout exceeded waiting for box to become available - Please verify box creation in HCP Vagrant and try again."))
return multistep.ActionHalt
}

return multistep.ActionContinue
}
Expand Down