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  }