github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/communicator/winrm/provisioner.go (about)

     1  package winrm
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"path/filepath"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/hashicorp/terraform/terraform"
    11  	"github.com/mitchellh/mapstructure"
    12  )
    13  
    14  const (
    15  	// DefaultUser is used if there is no user given
    16  	DefaultUser = "Administrator"
    17  
    18  	// DefaultPort is used if there is no port given
    19  	DefaultPort = 5985
    20  
    21  	// DefaultScriptPath is used as the path to copy the file to
    22  	// for remote execution if not provided otherwise.
    23  	DefaultScriptPath = "C:/Temp/terraform_%RAND%.cmd"
    24  
    25  	// DefaultTimeout is used if there is no timeout given
    26  	DefaultTimeout = 5 * time.Minute
    27  )
    28  
    29  // connectionInfo is decoded from the ConnInfo of the resource. These are the
    30  // only keys we look at. If a KeyFile is given, that is used instead
    31  // of a password.
    32  type connectionInfo struct {
    33  	User       string
    34  	Password   string
    35  	Host       string
    36  	Port       int
    37  	HTTPS      bool
    38  	Insecure   bool
    39  	CACert     *[]byte `mapstructure:"ca_cert"`
    40  	Timeout    string
    41  	ScriptPath string        `mapstructure:"script_path"`
    42  	TimeoutVal time.Duration `mapstructure:"-"`
    43  }
    44  
    45  // parseConnectionInfo is used to convert the ConnInfo of the InstanceState into
    46  // a ConnectionInfo struct
    47  func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
    48  	connInfo := &connectionInfo{}
    49  	decConf := &mapstructure.DecoderConfig{
    50  		WeaklyTypedInput: true,
    51  		Result:           connInfo,
    52  	}
    53  	dec, err := mapstructure.NewDecoder(decConf)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	if err := dec.Decode(s.Ephemeral.ConnInfo); err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	// Check on script paths which point to the default Windows TEMP folder because files
    62  	// which are put in there very early in the boot process could get cleaned/deleted
    63  	// before you had the change to execute them.
    64  	//
    65  	// TODO (SvH) Needs some more debugging to fully understand the exact sequence of events
    66  	// causing this...
    67  	if strings.HasPrefix(filepath.ToSlash(connInfo.ScriptPath), "C:/Windows/Temp") {
    68  		return nil, fmt.Errorf(
    69  			`Using the C:\Windows\Temp folder is not supported. Please use a different 'script_path'.`)
    70  	}
    71  
    72  	if connInfo.User == "" {
    73  		connInfo.User = DefaultUser
    74  	}
    75  	if connInfo.Port == 0 {
    76  		connInfo.Port = DefaultPort
    77  	}
    78  	if connInfo.ScriptPath == "" {
    79  		connInfo.ScriptPath = DefaultScriptPath
    80  	}
    81  	if connInfo.Timeout != "" {
    82  		connInfo.TimeoutVal = safeDuration(connInfo.Timeout, DefaultTimeout)
    83  	} else {
    84  		connInfo.TimeoutVal = DefaultTimeout
    85  	}
    86  
    87  	return connInfo, nil
    88  }
    89  
    90  // safeDuration returns either the parsed duration or a default value
    91  func safeDuration(dur string, defaultDur time.Duration) time.Duration {
    92  	d, err := time.ParseDuration(dur)
    93  	if err != nil {
    94  		log.Printf("Invalid duration '%s', using default of %s", dur, defaultDur)
    95  		return defaultDur
    96  	}
    97  	return d
    98  }
    99  
   100  func formatDuration(duration time.Duration) string {
   101  	h := int(duration.Hours())
   102  	m := int(duration.Minutes()) - h*60
   103  	s := int(duration.Seconds()) - (h*3600 + m*60)
   104  
   105  	res := "PT"
   106  	if h > 0 {
   107  		res = fmt.Sprintf("%s%dH", res, h)
   108  	}
   109  	if m > 0 {
   110  		res = fmt.Sprintf("%s%dM", res, m)
   111  	}
   112  	if s > 0 {
   113  		res = fmt.Sprintf("%s%dS", res, s)
   114  	}
   115  
   116  	return res
   117  }