github.com/dacamp/packer@v0.10.2/provisioner/shell-local/provisioner.go (about) 1 package shell 2 3 import ( 4 "errors" 5 "fmt" 6 "runtime" 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 // Command is the command to execute 18 Command string 19 20 // ExecuteCommand is the command used to execute the command. 21 ExecuteCommand []string `mapstructure:"execute_command"` 22 23 ctx interpolate.Context 24 } 25 26 type Provisioner struct { 27 config Config 28 } 29 30 func (p *Provisioner) Prepare(raws ...interface{}) error { 31 err := config.Decode(&p.config, &config.DecodeOpts{ 32 Interpolate: true, 33 InterpolateContext: &p.config.ctx, 34 InterpolateFilter: &interpolate.RenderFilter{ 35 Exclude: []string{ 36 "execute_command", 37 }, 38 }, 39 }, raws...) 40 if err != nil { 41 return err 42 } 43 44 if len(p.config.ExecuteCommand) == 0 { 45 if runtime.GOOS == "windows" { 46 p.config.ExecuteCommand = []string{ 47 "cmd", 48 "/C", 49 "{{.Command}}", 50 } 51 } else { 52 p.config.ExecuteCommand = []string{ 53 "/bin/sh", 54 "-c", 55 "{{.Command}}", 56 } 57 } 58 } 59 60 var errs *packer.MultiError 61 if p.config.Command == "" { 62 errs = packer.MultiErrorAppend(errs, 63 errors.New("command must be specified")) 64 } 65 66 if len(p.config.ExecuteCommand) == 0 { 67 errs = packer.MultiErrorAppend(errs, 68 errors.New("execute_command must not be empty")) 69 } 70 71 if errs != nil && len(errs.Errors) > 0 { 72 return errs 73 } 74 75 return nil 76 } 77 78 func (p *Provisioner) Provision(ui packer.Ui, _ packer.Communicator) error { 79 // Make another communicator for local 80 comm := &Communicator{ 81 Ctx: p.config.ctx, 82 ExecuteCommand: p.config.ExecuteCommand, 83 } 84 85 // Build the remote command 86 cmd := &packer.RemoteCmd{Command: p.config.Command} 87 88 ui.Say(fmt.Sprintf( 89 "Executing local command: %s", 90 p.config.Command)) 91 if err := cmd.StartWithUi(comm, ui); err != nil { 92 return fmt.Errorf( 93 "Error executing command: %s\n\n"+ 94 "Please see output above for more information.", 95 p.config.Command) 96 } 97 if cmd.ExitStatus != 0 { 98 return fmt.Errorf( 99 "Erroneous exit code %d while executing command: %s\n\n"+ 100 "Please see output above for more information.", 101 cmd.ExitStatus, 102 p.config.Command) 103 } 104 105 return nil 106 } 107 108 func (p *Provisioner) Cancel() { 109 // Just do nothing. When the process ends, so will our provisioner 110 }