github.com/turbot/go-exec-communicator@v0.0.0-20230412124734-9374347749b6/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/turbot/go-exec-communicator/shared" 11 ) 12 13 const ( 14 // DefaultUser is used if there is no user given 15 DefaultUser = "Administrator" 16 17 // DefaultPort is used if there is no port given 18 DefaultPort = 5985 19 20 // DefaultHTTPSPort is used if there is no port given and HTTPS is true 21 DefaultHTTPSPort = 5986 22 23 // DefaultScriptPath is used as the path to copy the file to 24 // for remote execution if not provided otherwise. 25 DefaultScriptPath = "C:/Temp/terraform_%RAND%.cmd" 26 27 // DefaultTimeout is used if there is no timeout given 28 DefaultTimeout = 5 * time.Minute 29 ) 30 31 /* 32 33 // shared.ConnectionInfo is decoded from the ConnInfo of the resource. These are the 34 // only keys we look at. If a KeyFile is given, that is used instead 35 // of a password. 36 type ConnectionInfo struct { 37 User string 38 Password string 39 Host string 40 Port uint16 41 HTTPS bool 42 Insecure bool 43 NTLM bool `mapstructure:"use_ntlm"` 44 CACert string `mapstructure:"cacert"` 45 Timeout string 46 ScriptPath string `mapstructure:"script_path"` 47 TimeoutVal time.Duration `mapstructure:"-"` 48 } 49 50 */ 51 52 /* 53 54 // decodeConnInfo decodes the given cty.Value using the same behavior as the 55 // lgeacy mapstructure decoder in order to preserve as much of the existing 56 // logic as possible for compatibility. 57 func decodeConnInfo(v cty.Value) (*shared.ConnectionInfo, error) { 58 connInfo := &shared.ConnectionInfo{} 59 if v.IsNull() { 60 return connInfo, nil 61 } 62 63 for k, v := range v.AsValueMap() { 64 if v.IsNull() { 65 continue 66 } 67 68 switch k { 69 case "user": 70 connInfo.User = v.AsString() 71 case "password": 72 connInfo.Password = v.AsString() 73 case "host": 74 connInfo.Host = v.AsString() 75 case "port": 76 if err := gocty.FromCtyValue(v, &connInfo.Port); err != nil { 77 return nil, err 78 } 79 case "https": 80 connInfo.HTTPS = v.True() 81 case "insecure": 82 connInfo.Insecure = v.True() 83 case "use_ntlm": 84 connInfo.NTLM = v.True() 85 case "cacert": 86 connInfo.CACert = v.AsString() 87 case "script_path": 88 connInfo.ScriptPath = v.AsString() 89 case "timeout": 90 connInfo.Timeout = v.AsString() 91 } 92 } 93 return connInfo, nil 94 } 95 96 */ 97 98 // parseshared.ConnectionInfo is used to convert the ConnInfo of the InstanceState into 99 // a shared.ConnectionInfo struct 100 func parseConnectionInfo(ci shared.ConnectionInfo) (*shared.ConnectionInfo, error) { 101 102 connInfo := ci 103 104 /* 105 v, err := shared.ConnectionBlockSupersetSchema.CoerceValue(v) 106 if err != nil { 107 return nil, err 108 } 109 110 connInfo, err := decodeConnInfo(v) 111 if err != nil { 112 return nil, err 113 } 114 */ 115 116 // Check on script paths which point to the default Windows TEMP folder because files 117 // which are put in there very early in the boot process could get cleaned/deleted 118 // before you had the change to execute them. 119 // 120 // TODO (SvH) Needs some more debugging to fully understand the exact sequence of events 121 // causing this... 122 if strings.HasPrefix(filepath.ToSlash(connInfo.ScriptPath), "C:/Windows/Temp") { 123 return nil, fmt.Errorf( 124 `Using the C:\Windows\Temp folder is not supported. Please use a different 'script_path'.`) 125 } 126 127 if connInfo.User == "" { 128 connInfo.User = DefaultUser 129 } 130 131 // Format the host if needed. 132 // Needed for IPv6 support. 133 connInfo.Host = shared.IpFormat(connInfo.Host) 134 135 if connInfo.Port == 0 { 136 if connInfo.HTTPS { 137 connInfo.Port = DefaultHTTPSPort 138 } else { 139 connInfo.Port = DefaultPort 140 } 141 } 142 if connInfo.ScriptPath == "" { 143 connInfo.ScriptPath = DefaultScriptPath 144 } 145 if connInfo.Timeout != "" { 146 connInfo.TimeoutVal = safeDuration(connInfo.Timeout, DefaultTimeout) 147 } else { 148 connInfo.TimeoutVal = DefaultTimeout 149 } 150 151 return &connInfo, nil 152 } 153 154 // safeDuration returns either the parsed duration or a default value 155 func safeDuration(dur string, defaultDur time.Duration) time.Duration { 156 d, err := time.ParseDuration(dur) 157 if err != nil { 158 log.Printf("Invalid duration '%s', using default of %s", dur, defaultDur) 159 return defaultDur 160 } 161 return d 162 } 163 164 func formatDuration(duration time.Duration) string { 165 h := int(duration.Hours()) 166 m := int(duration.Minutes()) - h*60 167 s := int(duration.Seconds()) - (h*3600 + m*60) 168 169 res := "PT" 170 if h > 0 { 171 res = fmt.Sprintf("%s%dH", res, h) 172 } 173 if m > 0 { 174 res = fmt.Sprintf("%s%dM", res, m) 175 } 176 if s > 0 { 177 res = fmt.Sprintf("%s%dS", res, s) 178 } 179 180 return res 181 }