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
10 changes: 10 additions & 0 deletions docs/post-processors/vagrant-cloud.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ on Vagrant Cloud, as well as authentication and version information.
- `Provider`: The Vagrant provider the box is for
- `ArtifactId`: The ID of the input artifact.

- `box_checksum` (string) - Optional checksum for the provider .box file.
The type of the checksum is specified within the checksum field as a prefix,
ex: "md5:{$checksum}". Valid values are:
- null or ""
- "md5:{$checksum}"
- "sha1:{$checksum}"
- "sha256:{$checksum}"
- "sha512:{$checksum}"
See https://www.vagrantup.com/vagrant-cloud/api#arguments-7

- `no_direct_upload` (boolean) - When `true`, upload the box artifact through
Vagrant Cloud instead of directly to the backend storage.

Expand Down
9 changes: 9 additions & 0 deletions post-processor/vagrant-cloud/post-processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"compress/gzip"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -48,6 +49,7 @@ type Config struct {
InsecureSkipTLSVerify bool `mapstructure:"insecure_skip_tls_verify"`
BoxDownloadUrl string `mapstructure:"box_download_url"`
NoDirectUpload bool `mapstructure:"no_direct_upload"`
BoxChecksum string `mapstructure:"box_checksum"`

ctx interpolate.Context
}
Expand Down Expand Up @@ -171,6 +173,12 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifa
return nil, false, false, fmt.Errorf("Error processing box_download_url: %s", err)
}

if p.config.BoxChecksum != "" {
if checksumParts := strings.SplitN(p.config.BoxChecksum, ":", 2); len(checksumParts) != 2 {
return nil, false, false, errors.New(" box checksum must be specified as `$type:$digest`")
}
}

// Set up the state
state := new(multistep.BasicStateBag)
state.Put("config", &p.config)
Expand All @@ -180,6 +188,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifa
state.Put("ui", ui)
state.Put("providerName", providerName)
state.Put("boxDownloadUrl", boxDownloadUrl)
state.Put("boxChecksum", p.config.BoxChecksum)

// Build the steps
steps := []multistep.Step{
Expand Down
2 changes: 2 additions & 0 deletions post-processor/vagrant-cloud/post-processor.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions post-processor/vagrant-cloud/post-processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ func testGoodConfig() map[string]interface{} {
"version_description": "bar",
"box_tag": "hashicorp/precise64",
"version": "0.5",
"box_checksum": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", // /dev/null
}
}

func testBadChecksumSpec() map[string]interface{} {
return map[string]interface{}{
"access_token": "foo",
"version_description": "bar",
"box_tag": "hashicorp/precise64",
"version": "0.5",
"box_checksum": "test",
}
}

Expand Down Expand Up @@ -229,6 +240,55 @@ func TestPostProcessor_Configure_checkAccessTokenIsNotRequiredForOverridenVagran
}
}

func TestPostProcessor_PostProcess_badChecksumSpec(t *testing.T) {
files := tarFiles{
{"foo.txt", "This is a foo file"},
{"bar.txt", "This is a bar file"},
{"metadata.json", `{"provider": "virtualbox"}`},
}
boxfile, err := createBox(files)
if err != nil {
t.Fatalf("%s", err)
}
defer os.Remove(boxfile.Name())

artifact := &packersdk.MockArtifact{
BuilderIdValue: "mitchellh.post-processor.vagrant",
FilesValue: []string{boxfile.Name()},
}

s := newStackServer([]stubResponse{stubResponse{StatusCode: 200, Method: "PUT", Path: "/box-upload-path"}})
defer s.Close()

stack := []stubResponse{
stubResponse{StatusCode: 200, Method: "GET", Path: "/authenticate"},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64", Response: `{"tag": "hashicorp/precise64"}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/versions", Response: `{}`},
stubResponse{StatusCode: 200, Method: "POST", Path: "/box/hashicorp/precise64/version/0.5/providers", Response: `{}`},
stubResponse{StatusCode: 200, Method: "GET", Path: "/box/hashicorp/precise64/version/0.5/provider/id/upload", Response: `{"upload_path": "` + s.URL + `/box-upload-path"}`},
}

server := newStackServer(stack)
defer server.Close()
config := testBadChecksumSpec()
config["vagrant_cloud_url"] = server.URL

var p PostProcessor

err = p.Configure(config)
if err != nil {
t.Fatalf("err: %s", err)
}

_, _, _, err = p.PostProcess(context.Background(), testUi(), artifact)
if err == nil {
t.Fatal("Expected bad checksum spec error")
}
if !strings.Contains(err.Error(), "box checksum must be specified as") {
t.Fatalf("Unexpected error: %v", err)
}
}

func TestPostProcessor_PostProcess_checkArtifactType(t *testing.T) {
artifact := &packersdk.MockArtifact{
BuilderIdValue: "invalid.builder",
Expand Down
23 changes: 19 additions & 4 deletions post-processor/vagrant-cloud/step_create_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ package vagrantcloud

import (
"context"
"errors"
"fmt"
"strings"

"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)

type Provider struct {
Name string `json:"name"`
Url string `json:"url,omitempty"`
HostedToken string `json:"hosted_token,omitempty"`
UploadUrl string `json:"upload_url,omitempty"`
Name string `json:"name"`
Url string `json:"url,omitempty"`
HostedToken string `json:"hosted_token,omitempty"`
UploadUrl string `json:"upload_url,omitempty"`
Checksum string `json:"checksum,omitempty"`
ChecksumType string `json:"checksum_type,omitempty"`
}

type stepCreateProvider struct {
Expand All @@ -26,6 +30,7 @@ func (s *stepCreateProvider) Run(ctx context.Context, state multistep.StateBag)
version := state.Get("version").(*Version)
providerName := state.Get("providerName").(string)
downloadUrl := state.Get("boxDownloadUrl").(string)
checksum := state.Get("boxChecksum").(string)

path := fmt.Sprintf("box/%s/version/%v/providers", box.Tag, version.Version)

Expand All @@ -35,6 +40,16 @@ func (s *stepCreateProvider) Run(ctx context.Context, state multistep.StateBag)
provider.Url = downloadUrl
}

if checksum != "" {
checksumParts := strings.SplitN(checksum, ":", 2)
if len(checksumParts) != 2 {
state.Put("error", errors.New("Error parsing box_checksum: invalid format"))
return multistep.ActionHalt
}
provider.ChecksumType = checksumParts[0]
provider.Checksum = checksumParts[1]
}

// Wrap the provider in a provider object for the API
wrapper := make(map[string]interface{})
wrapper["provider"] = provider
Expand Down