Changed file builder to support content or source file operation

This commit is contained in:
Chris Bednarski 2015-06-12 18:18:38 -07:00
parent f7d85eb49c
commit e60b22d48f
3 changed files with 63 additions and 12 deletions

View File

@ -6,7 +6,10 @@ any virutalization or network resources, it's very fast and useful for testing.
*/
import (
"fmt"
"io"
"io/ioutil"
"os"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
@ -47,7 +50,35 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
artifact := new(FileArtifact)
ioutil.WriteFile(b.config.Filename, []byte(b.config.Contents), 0600)
if b.config.Source != "" {
source, err := os.Open(b.config.Source)
defer source.Close()
if err != nil {
return nil, err
}
target, err := os.OpenFile(b.config.Target, os.O_WRONLY, 0600)
defer target.Close()
if err != nil {
return nil, err
}
ui.Say(fmt.Sprintf("Copying %s to %s", source.Name(), target.Name()))
bytes, err := io.Copy(source, target)
if err != nil {
return nil, err
}
ui.Say(fmt.Sprintf("Copied %d bytes", bytes))
artifact.filename = target.Name()
} else {
// We're going to write Contents; if it's empty we'll just create an
// empty file.
err := ioutil.WriteFile(b.config.Target, []byte(b.config.Content), 0600)
if err != nil {
return nil, err
}
artifact.filename = b.config.Target
}
return artifact, nil
}

View File

@ -9,11 +9,15 @@ import (
"github.com/mitchellh/packer/template/interpolate"
)
var ErrTargetRequired = fmt.Errorf("target required")
var ErrContentSourceConflict = fmt.Errorf("Cannot specify source file AND content")
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Filename string `mapstructure:"filename"`
Contents string `mapstructure:"contents"`
Source string `mapstructure:"source"`
Target string `mapstructure:"target"`
Content string `mapstructure:"content"`
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
@ -32,12 +36,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
var errs *packer.MultiError
if c.Filename == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("filename is required"))
if c.Target == "" {
errs = packer.MultiErrorAppend(errs, ErrTargetRequired)
}
if c.Contents == "" {
warnings = append(warnings, "contents is empty")
if c.Content == "" && c.Source == "" {
warnings = append(warnings, "Both source file and contents are blank; target will have no content")
}
if c.Content != "" && c.Source != "" {
errs = packer.MultiErrorAppend(errs, ErrContentSourceConflict)
}
if errs != nil && len(errs.Errors) > 0 {

View File

@ -2,13 +2,24 @@ package file
import (
"fmt"
"strings"
"testing"
)
func testConfig() map[string]interface{} {
return map[string]interface{}{
"filename": "test.txt",
"contents": "Hello, world!",
"source": "src.txt",
"target": "dst.txt",
"content": "Hello, world!",
}
}
func TestContentSourceConflict(t *testing.T) {
raw := testConfig()
_, _, errs := NewConfig(raw)
if !strings.Contains(errs.Error(), ErrContentSourceConflict.Error()) {
t.Errorf("Expected config error: %s", ErrContentSourceConflict.Error())
}
}
@ -18,18 +29,19 @@ func TestNoFilename(t *testing.T) {
delete(raw, "filename")
_, _, errs := NewConfig(raw)
if errs == nil {
t.Error("Expected config to error without a filename")
t.Errorf("Expected config error: %s", ErrTargetRequired.Error())
}
}
func TestNoContent(t *testing.T) {
raw := testConfig()
delete(raw, "contents")
delete(raw, "content")
delete(raw, "source")
_, warns, _ := NewConfig(raw)
fmt.Println(len(warns))
fmt.Printf("%#v\n", warns)
if len(warns) == 0 {
t.Error("Expected config to warn without any content")
t.Error("Expected config warning without any content")
}
}