github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/provisioner/file/provisioner.go (about) 1 package file 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 8 "github.com/mitchellh/packer/common" 9 "github.com/mitchellh/packer/helper/config" 10 "github.com/mitchellh/packer/packer" 11 "github.com/mitchellh/packer/template/interpolate" 12 ) 13 14 type Config struct { 15 common.PackerConfig `mapstructure:",squash"` 16 17 // The local path of the file to upload. 18 Source string 19 20 // The remote path where the local file will be uploaded to. 21 Destination string 22 23 // Direction 24 Direction string 25 26 ctx interpolate.Context 27 } 28 29 type Provisioner struct { 30 config Config 31 } 32 33 func (p *Provisioner) Prepare(raws ...interface{}) error { 34 err := config.Decode(&p.config, &config.DecodeOpts{ 35 Interpolate: true, 36 InterpolateContext: &p.config.ctx, 37 InterpolateFilter: &interpolate.RenderFilter{ 38 Exclude: []string{}, 39 }, 40 }, raws...) 41 if err != nil { 42 return err 43 } 44 45 if p.config.Direction == "" { 46 p.config.Direction = "upload" 47 } 48 49 var errs *packer.MultiError 50 51 if p.config.Direction != "download" && p.config.Direction != "upload" { 52 errs = packer.MultiErrorAppend(errs, 53 errors.New("Direction must be one of: download, upload.")) 54 } 55 56 if p.config.Direction == "upload" { 57 if _, err := os.Stat(p.config.Source); err != nil { 58 errs = packer.MultiErrorAppend(errs, 59 fmt.Errorf("Bad source '%s': %s", p.config.Source, err)) 60 } 61 } 62 63 if p.config.Destination == "" { 64 errs = packer.MultiErrorAppend(errs, 65 errors.New("Destination must be specified.")) 66 } 67 68 if errs != nil && len(errs.Errors) > 0 { 69 return errs 70 } 71 72 return nil 73 } 74 75 func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { 76 if p.config.Direction == "download" { 77 return p.ProvisionDownload(ui, comm) 78 } else { 79 return p.ProvisionUpload(ui, comm) 80 } 81 } 82 83 func (p *Provisioner) ProvisionDownload(ui packer.Ui, comm packer.Communicator) error { 84 ui.Say(fmt.Sprintf("Downloading %s => %s", p.config.Source, p.config.Destination)) 85 86 f, err := os.OpenFile(p.config.Destination, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 87 if err != nil { 88 return err 89 } 90 defer f.Close() 91 92 err = comm.Download(p.config.Source, f) 93 if err != nil { 94 ui.Error(fmt.Sprintf("Download failed: %s", err)) 95 } 96 return err 97 } 98 99 func (p *Provisioner) ProvisionUpload(ui packer.Ui, comm packer.Communicator) error { 100 ui.Say(fmt.Sprintf("Uploading %s => %s", p.config.Source, p.config.Destination)) 101 info, err := os.Stat(p.config.Source) 102 if err != nil { 103 return err 104 } 105 106 // If we're uploading a directory, short circuit and do that 107 if info.IsDir() { 108 return comm.UploadDir(p.config.Destination, p.config.Source, nil) 109 } 110 111 // We're uploading a file... 112 f, err := os.Open(p.config.Source) 113 if err != nil { 114 return err 115 } 116 defer f.Close() 117 118 fi, err := f.Stat() 119 if err != nil { 120 return err 121 } 122 123 err = comm.Upload(p.config.Destination, f, &fi) 124 if err != nil { 125 ui.Error(fmt.Sprintf("Upload failed: %s", err)) 126 } 127 return err 128 } 129 130 func (p *Provisioner) Cancel() { 131 // Just hard quit. It isn't a big deal if what we're doing keeps 132 // running on the other side. 133 os.Exit(0) 134 }