github.phpd.cn/hashicorp/packer@v1.3.2/builder/file/builder.go (about) 1 package file 2 3 /* 4 The File builder creates an artifact from a file. Because it does not require 5 any virtualization or network resources, it's very fast and useful for testing. 6 */ 7 8 import ( 9 "fmt" 10 "io" 11 "io/ioutil" 12 "os" 13 14 "github.com/hashicorp/packer/helper/multistep" 15 "github.com/hashicorp/packer/packer" 16 ) 17 18 const BuilderId = "packer.file" 19 20 type Builder struct { 21 config *Config 22 runner multistep.Runner 23 } 24 25 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 26 c, warnings, errs := NewConfig(raws...) 27 if errs != nil { 28 return warnings, errs 29 } 30 b.config = c 31 32 return warnings, nil 33 } 34 35 // Run is where the actual build should take place. It takes a Build and a Ui. 36 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 37 artifact := new(FileArtifact) 38 39 if b.config.Source != "" { 40 source, err := os.Open(b.config.Source) 41 defer source.Close() 42 if err != nil { 43 return nil, err 44 } 45 46 // Create will truncate an existing file 47 target, err := os.Create(b.config.Target) 48 defer target.Close() 49 if err != nil { 50 return nil, err 51 } 52 53 ui.Say(fmt.Sprintf("Copying %s to %s", source.Name(), target.Name())) 54 bytes, err := io.Copy(target, source) 55 if err != nil { 56 return nil, err 57 } 58 ui.Say(fmt.Sprintf("Copied %d bytes", bytes)) 59 artifact.filename = target.Name() 60 } else { 61 // We're going to write Contents; if it's empty we'll just create an 62 // empty file. 63 err := ioutil.WriteFile(b.config.Target, []byte(b.config.Content), 0600) 64 if err != nil { 65 return nil, err 66 } 67 artifact.filename = b.config.Target 68 } 69 70 return artifact, nil 71 } 72 73 // Cancel cancels a possibly running Builder. This should block until 74 // the builder actually cancels and cleans up after itself. 75 func (b *Builder) Cancel() { 76 b.runner.Cancel() 77 }