Skip to content

Commit

Permalink
Merge pull request #32 from dweomer/feat/31/post-processor/vagrant-cl…
Browse files Browse the repository at this point in the history
…oud/provider-checksums

[vagrant-cloud post-processor] box checksums
  • Loading branch information
nywilken authored Nov 12, 2021
2 parents f200290 + 50b41b8 commit d9d2f9a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 4 deletions.
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

0 comments on commit d9d2f9a

Please sign in to comment.