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