github.com/bigkraig/terraform@v0.6.4-0.20151219155159-c90d1b074e31/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 }