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  }