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  }