github.com/kikitux/packer@v0.10.1-0.20160322154024-6237df566f9f/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 func (c *Config) Prepare(ctx *interpolate.Context) []error { 59 if c.Type == "" { 60 c.Type = "ssh" 61 } 62 63 var errs []error 64 switch c.Type { 65 case "ssh": 66 if es := c.prepareSSH(ctx); len(es) > 0 { 67 errs = append(errs, es...) 68 } 69 case "winrm": 70 if es := c.prepareWinRM(ctx); len(es) > 0 { 71 errs = append(errs, es...) 72 } 73 case "docker", "none": 74 break 75 default: 76 return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)} 77 } 78 79 return errs 80 } 81 82 func (c *Config) prepareSSH(ctx *interpolate.Context) []error { 83 if c.SSHPort == 0 { 84 c.SSHPort = 22 85 } 86 87 if c.SSHTimeout == 0 { 88 c.SSHTimeout = 5 * time.Minute 89 } 90 91 if c.SSHHandshakeAttempts == 0 { 92 c.SSHHandshakeAttempts = 10 93 } 94 95 if c.SSHBastionHost != "" { 96 if c.SSHBastionPort == 0 { 97 c.SSHBastionPort = 22 98 } 99 100 if c.SSHBastionPrivateKey == "" && c.SSHPrivateKey != "" { 101 c.SSHBastionPrivateKey = c.SSHPrivateKey 102 } 103 } 104 105 if c.SSHFileTransferMethod == "" { 106 c.SSHFileTransferMethod = "scp" 107 } 108 109 // Validation 110 var errs []error 111 if c.SSHUsername == "" { 112 errs = append(errs, errors.New("An ssh_username must be specified")) 113 } 114 115 if c.SSHPrivateKey != "" { 116 if _, err := os.Stat(c.SSHPrivateKey); err != nil { 117 errs = append(errs, fmt.Errorf( 118 "ssh_private_key_file is invalid: %s", err)) 119 } else if _, err := SSHFileSigner(c.SSHPrivateKey); err != nil { 120 errs = append(errs, fmt.Errorf( 121 "ssh_private_key_file is invalid: %s", err)) 122 } 123 } 124 125 if c.SSHBastionHost != "" { 126 if c.SSHBastionPassword == "" && c.SSHBastionPrivateKey == "" { 127 errs = append(errs, errors.New( 128 "ssh_bastion_password or ssh_bastion_private_key_file must be specified")) 129 } 130 } 131 132 if c.SSHFileTransferMethod != "scp" && c.SSHFileTransferMethod != "sftp" { 133 errs = append(errs, fmt.Errorf( 134 "ssh_file_transfer_method ('%s') is invalid, valid methods: sftp, scp", 135 c.SSHFileTransferMethod)) 136 } 137 138 return errs 139 } 140 141 func (c *Config) prepareWinRM(ctx *interpolate.Context) []error { 142 if c.WinRMPort == 0 && c.WinRMUseSSL { 143 c.WinRMPort = 5986 144 } else if c.WinRMPort == 0 { 145 c.WinRMPort = 5985 146 } 147 148 if c.WinRMTimeout == 0 { 149 c.WinRMTimeout = 30 * time.Minute 150 } 151 152 var errs []error 153 if c.WinRMUser == "" { 154 errs = append(errs, errors.New("winrm_username must be specified.")) 155 } 156 157 return errs 158 }