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  }