From b695615d7d4554330790e8c777c9864456ad5ef0 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 29 Jul 2020 01:26:09 -0700 Subject: [PATCH] fix local file stating (#9660) --- builder/vagrant/builder.go | 16 ++++++++++--- builder/vagrant/builder_test.go | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/builder/vagrant/builder.go b/builder/vagrant/builder.go index 8bd38c379..045aa47c7 100644 --- a/builder/vagrant/builder.go +++ b/builder/vagrant/builder.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "net/url" "os" "path/filepath" "strings" @@ -194,10 +195,19 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { if b.config.GlobalID != "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("You may either set global_id or source_path but not both")) } + // We're about to open up an actual boxfile. If the file is local to the + // filesystem, let's make sure it exists before we get too far into the + // build. if strings.HasSuffix(b.config.SourceBox, ".box") { - if _, err := os.Stat(b.config.SourceBox); err != nil { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("Source box '%s' needs to exist at time of config validation! %v", b.config.SourceBox, err)) + // If scheme is "file" or empty, then we need to check the + // filesystem to make sure the box is present locally. + u, err := url.Parse(b.config.SourceBox) + if err == nil && (u.Scheme == "" || u.Scheme == "file") { + if _, err := os.Stat(b.config.SourceBox); err != nil { + errs = packer.MultiErrorAppend(errs, + fmt.Errorf("Source box '%s' needs to exist at time of"+ + " config validation! %v", b.config.SourceBox, err)) + } } } } diff --git a/builder/vagrant/builder_test.go b/builder/vagrant/builder_test.go index 704c23f2a..177e81c0f 100644 --- a/builder/vagrant/builder_test.go +++ b/builder/vagrant/builder_test.go @@ -79,6 +79,46 @@ func TestBuilder_Prepare_ValidateSource(t *testing.T) { errExpected: true, reason: "Inalid argument for teardown method", }, + { + config: map[string]interface{}{ + "communicator": "ssh", + "source_path": "./my.box", + }, + errExpected: true, + reason: "Should fail because path does not exist", + }, + { + config: map[string]interface{}{ + "communicator": "ssh", + "source_path": "file://my.box", + }, + errExpected: true, + reason: "Should fail because path does not exist", + }, + { + config: map[string]interface{}{ + "communicator": "ssh", + "source_path": "http://my.box", + }, + errExpected: false, + reason: "Should pass because path is not local", + }, + { + config: map[string]interface{}{ + "communicator": "ssh", + "source_path": "https://my.box", + }, + errExpected: false, + reason: "Should pass because path is not local", + }, + { + config: map[string]interface{}{ + "communicator": "ssh", + "source_path": "smb://my.box", + }, + errExpected: false, + reason: "Should pass because path is not local", + }, } for _, tc := range cases {