file provisioner: download should create all dirs in the destination path

This commit is contained in:
Joel Scoble 2016-07-06 15:42:26 -05:00
parent 664e640257
commit 999b8b2ed0
2 changed files with 70 additions and 4 deletions

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/mitchellh/packer/common"
@ -95,12 +96,20 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error {
for _, src := range p.config.Sources {
ui.Say(fmt.Sprintf("Downloading %s => %s", src, p.config.Destination))
if strings.HasSuffix(p.config.Destination, "/") {
err := os.MkdirAll(p.config.Destination, os.FileMode(0755))
// ensure destination dir exists. p.config.Destination may either be a file or a dir.
dir := p.config.Destination
// if it doesn't end with a /, set dir as the parent dir
if !strings.HasSuffix(p.config.Destination, "/") {
dir = filepath.Dir(dir)
}
if dir != "" {
err := os.MkdirAll(dir, os.FileMode(0755))
if err != nil {
return err
}
}
// if the config.Destination was a dir, download the dir
if !strings.HasSuffix(p.config.Destination, "/") {
return comm.DownloadDir(src, p.config.Destination, nil)
}

View File

@ -1,11 +1,14 @@
package file
import (
"github.com/mitchellh/packer/packer"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/mitchellh/packer/packer"
)
func testConfig() map[string]interface{} {
@ -139,3 +142,57 @@ func TestProvisionerProvision_SendsFile(t *testing.T) {
t.Fatalf("should upload with source file's data")
}
}
func TestProvisionDownloadMkdirAll(t *testing.T) {
tests := []struct {
path string
}{
{"dir"},
{"dir/"},
{"dir/subdir"},
{"dir/subdir/"},
{"path/to/dir"},
{"path/to/dir/"},
}
tmpDir, err := ioutil.TempDir("", "packer-file")
if err != nil {
t.Fatalf("error tempdir: %s", err)
}
defer os.RemoveAll(tmpDir)
tf, err := ioutil.TempFile(tmpDir, "packer")
if err != nil {
t.Fatalf("error tempfile: %s", err)
}
fmt.Println(tf.Name())
defer os.Remove(tf.Name())
config := map[string]interface{}{
"source": tf.Name(),
}
var p Provisioner
for _, test := range tests {
path := filepath.Join(tmpDir, test.path)
config["destination"] = filepath.Join(path, "something")
if err := p.Prepare(config); err != nil {
t.Fatalf("err: %s", err)
}
ui := &stubUi{}
comm := &packer.MockCommunicator{}
err = p.ProvisionDownload(ui, comm)
if err != nil {
t.Fatalf("should successfully provision: %s", err)
}
if !strings.Contains(ui.sayMessages, tf.Name()) {
t.Fatalf("should print source filename")
}
if !strings.Contains(ui.sayMessages, "something") {
t.Fatalf("should print destination filename")
}
if _, err := os.Stat(path); err != nil {
t.Fatalf("stat of download dir should not error: %s", err)
}
}
}