github.com/marksheahan/packer@v0.10.2-0.20160613200515-1acb2d6645a0/helper/communicator/config.go (about) 1 package communicator 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "os" 8 "time" 9 10 "github.com/mitchellh/packer/template/interpolate" 11 ) 12 13 // Config is the common configuration that communicators allow within 14 // a builder. 15 type Config struct { 16 Type string `mapstructure:"communicator"` 17 18 // SSH 19 SSHHost string `mapstructure:"ssh_host"` 20 SSHPort int `mapstructure:"ssh_port"` 21 SSHUsername string `mapstructure:"ssh_username"` 22 SSHPassword string `mapstructure:"ssh_password"` 23 SSHPrivateKey string `mapstructure:"ssh_private_key_file"` 24 SSHPty bool `mapstructure:"ssh_pty"` 25 SSHTimeout time.Duration `mapstructure:"ssh_timeout"` 26 SSHDisableAgent bool `mapstructure:"ssh_disable_agent"` 27 SSHHandshakeAttempts int `mapstructure:"ssh_handshake_attempts"` 28 SSHBastionHost string `mapstructure:"ssh_bastion_host"` 29 SSHBastionPort int `mapstructure:"ssh_bastion_port"` 30 SSHBastionUsername string `mapstructure:"ssh_bastion_username"` 31 SSHBastionPassword string `mapstructure:"ssh_bastion_password"` 32 SSHBastionPrivateKey string `mapstructure:"ssh_bastion_private_key_file"` 33 SSHFileTransferMethod string `mapstructure:"ssh_file_transfer_method"` 34 35 // WinRM 36 WinRMUser string `mapstructure:"winrm_username"` 37 WinRMPassword string `mapstructure:"winrm_password"` 38 WinRMHost string `mapstructure:"winrm_host"` 39 WinRMPort int `mapstructure:"winrm_port"` 40 WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` 41 WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` 42 WinRMInsecure bool `mapstructure:"winrm_insecure"` 43 WinRMTransportDecorator func(*http.Transport) http.RoundTripper 44 } 45 46 // Port returns the port that will be used for access based on config. 47 func (c *Config) Port() int { 48 switch c.Type { 49 case "ssh": 50 return c.SSHPort 51 case "winrm": 52 return c.WinRMPort 53 default: 54 return 0 55 } 56 } 57 58 // Host returns the port that will be used for access based on config. 59 func (c *Config) Host() string { 60 switch c.Type { 61 case "ssh": 62 return c.SSHHost 63 case "winrm": 64 return c.WinRMHost 65 default: 66 return "" 67 } 68 } 69 70 // User returns the port that will be used for access based on config. 71 func (c *Config) User() string { 72 switch c.Type { 73 case "ssh": 74 return c.SSHUsername 75 case "winrm": 76 return c.WinRMUser 77 default: 78 return "" 79 } 80 } 81 82 // Password returns the port that will be used for access based on config. 83 func (c *Config) Password() string { 84 switch c.Type { 85 case "ssh": 86 return c.SSHPassword 87 case "winrm": 88 return c.WinRMPassword 89 default: 90 return "" 91 } 92 } 93 94 func (c *Config) Prepare(ctx *interpolate.Context) []error { 95 if c.Type == "" { 96 c.Type = "ssh" 97 } 98 99 var errs []error 100 switch c.Type { 101 case "ssh": 102 if es := c.prepareSSH(ctx); len(es) > 0 { 103 errs = append(errs, es...) 104 } 105 case "winrm": 106 if es := c.prepareWinRM(ctx); len(es) > 0 { 107 errs = append(errs, es...) 108 } 109 case "docker", "none": 110 break 111 default: 112 return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)} 113 } 114 115 return errs 116 } 117 118 func (c *Config) prepareSSH(ctx *interpolate.Context) []error { 119 if c.SSHPort == 0 { 120 c.SSHPort = 22 121 } 122 123 if c.SSHTimeout == 0 { 124 c.SSHTimeout = 5 * time.Minute 125 } 126 127 if c.SSHHandshakeAttempts == 0 { 128 c.SSHHandshakeAttempts = 10 129 } 130 131 if c.SSHBastionHost != "" { 132 if c.SSHBastionPort == 0 { 133 c.SSHBastionPort = 22 134 } 135 136 if c.SSHBastionPrivateKey == "" && c.SSHPrivateKey != "" { 137 c.SSHBastionPrivateKey = c.SSHPrivateKey 138 } 139 } 140 141 if c.SSHFileTransferMethod == "" { 142 c.SSHFileTransferMethod = "scp" 143 } 144 145 // Validation 146 var errs []error 147 if c.SSHUsername == "" { 148 errs = append(errs, errors.New("An ssh_username must be specified")) 149 } 150 151 if c.SSHPrivateKey != "" { 152 if _, err := os.Stat(c.SSHPrivateKey); err != nil { 153 errs = append(errs, fmt.Errorf( 154 "ssh_private_key_file is invalid: %s", err)) 155 } else if _, err := SSHFileSigner(c.SSHPrivateKey); err != nil { 156 errs = append(errs, fmt.Errorf( 157 "ssh_private_key_file is invalid: %s", err)) 158 } 159 } 160 161 if c.SSHBastionHost != "" { 162 if c.SSHBastionPassword == "" && c.SSHBastionPrivateKey == "" { 163 errs = append(errs, errors.New( 164 "ssh_bastion_password or ssh_bastion_private_key_file must be specified")) 165 } 166 } 167 168 if c.SSHFileTransferMethod != "scp" && c.SSHFileTransferMethod != "sftp" { 169 errs = append(errs, fmt.Errorf( 170 "ssh_file_transfer_method ('%s') is invalid, valid methods: sftp, scp", 171 c.SSHFileTransferMethod)) 172 } 173 174 return errs 175 } 176 177 func (c *Config) prepareWinRM(ctx *interpolate.Context) []error { 178 if c.WinRMPort == 0 && c.WinRMUseSSL { 179 c.WinRMPort = 5986 180 } else if c.WinRMPort == 0 { 181 c.WinRMPort = 5985 182 } 183 184 if c.WinRMTimeout == 0 { 185 c.WinRMTimeout = 30 * time.Minute 186 } 187 188 var errs []error 189 if c.WinRMUser == "" { 190 errs = append(errs, errors.New("winrm_username must be specified.")) 191 } 192 193 return errs 194 }