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  }