github.com/kimor79/packer@v0.8.7-0.20151221212622-d507b18eb4cf/helper/communicator/config.go (about) 1 package communicator 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "time" 8 9 "github.com/mitchellh/packer/template/interpolate" 10 ) 11 12 // Config is the common configuration that communicators allow within 13 // a builder. 14 type Config struct { 15 Type string `mapstructure:"communicator"` 16 17 // SSH 18 SSHHost string `mapstructure:"ssh_host"` 19 SSHPort int `mapstructure:"ssh_port"` 20 SSHUsername string `mapstructure:"ssh_username"` 21 SSHPassword string `mapstructure:"ssh_password"` 22 SSHPrivateKey string `mapstructure:"ssh_private_key_file"` 23 SSHPty bool `mapstructure:"ssh_pty"` 24 SSHTimeout time.Duration `mapstructure:"ssh_timeout"` 25 SSHDisableAgent bool `mapstructure:"ssh_disable_agent"` 26 SSHHandshakeAttempts int `mapstructure:"ssh_handshake_attempts"` 27 SSHBastionHost string `mapstructure:"ssh_bastion_host"` 28 SSHBastionPort int `mapstructure:"ssh_bastion_port"` 29 SSHBastionUsername string `mapstructure:"ssh_bastion_username"` 30 SSHBastionPassword string `mapstructure:"ssh_bastion_password"` 31 SSHBastionPrivateKey string `mapstructure:"ssh_bastion_private_key_file"` 32 33 // WinRM 34 WinRMUser string `mapstructure:"winrm_username"` 35 WinRMPassword string `mapstructure:"winrm_password"` 36 WinRMHost string `mapstructure:"winrm_host"` 37 WinRMPort int `mapstructure:"winrm_port"` 38 WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` 39 } 40 41 // Port returns the port that will be used for access based on config. 42 func (c *Config) Port() int { 43 switch c.Type { 44 case "ssh": 45 return c.SSHPort 46 case "winrm": 47 return c.WinRMPort 48 default: 49 return 0 50 } 51 } 52 53 func (c *Config) Prepare(ctx *interpolate.Context) []error { 54 if c.Type == "" { 55 c.Type = "ssh" 56 } 57 58 var errs []error 59 switch c.Type { 60 case "ssh": 61 if es := c.prepareSSH(ctx); len(es) > 0 { 62 errs = append(errs, es...) 63 } 64 case "winrm": 65 if es := c.prepareWinRM(ctx); len(es) > 0 { 66 errs = append(errs, es...) 67 } 68 case "docker", "none": 69 break 70 default: 71 return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)} 72 } 73 74 return errs 75 } 76 77 func (c *Config) prepareSSH(ctx *interpolate.Context) []error { 78 if c.SSHPort == 0 { 79 c.SSHPort = 22 80 } 81 82 if c.SSHTimeout == 0 { 83 c.SSHTimeout = 5 * time.Minute 84 } 85 86 if c.SSHHandshakeAttempts == 0 { 87 c.SSHHandshakeAttempts = 10 88 } 89 90 if c.SSHBastionHost != "" { 91 if c.SSHBastionPort == 0 { 92 c.SSHBastionPort = 22 93 } 94 95 if c.SSHBastionPrivateKey == "" && c.SSHPrivateKey != "" { 96 c.SSHBastionPrivateKey = c.SSHPrivateKey 97 } 98 } 99 100 // Validation 101 var errs []error 102 if c.SSHUsername == "" { 103 errs = append(errs, errors.New("An ssh_username must be specified")) 104 } 105 106 if c.SSHPrivateKey != "" { 107 if _, err := os.Stat(c.SSHPrivateKey); err != nil { 108 errs = append(errs, fmt.Errorf( 109 "ssh_private_key_file is invalid: %s", err)) 110 } else if _, err := SSHFileSigner(c.SSHPrivateKey); err != nil { 111 errs = append(errs, fmt.Errorf( 112 "ssh_private_key_file is invalid: %s", err)) 113 } 114 } 115 116 if c.SSHBastionHost != "" { 117 if c.SSHBastionPassword == "" && c.SSHBastionPrivateKey == "" { 118 errs = append(errs, errors.New( 119 "ssh_bastion_password or ssh_bastion_private_key_file must be specified")) 120 } 121 } 122 123 return errs 124 } 125 126 func (c *Config) prepareWinRM(ctx *interpolate.Context) []error { 127 if c.WinRMPort == 0 { 128 c.WinRMPort = 5985 129 } 130 131 if c.WinRMTimeout == 0 { 132 c.WinRMTimeout = 30 * time.Minute 133 } 134 135 var errs []error 136 if c.WinRMUser == "" { 137 errs = append(errs, errors.New("winrm_username must be specified.")) 138 } 139 140 return errs 141 }