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