communicator/ssh: Add support for Windows targets (#26865)
This commit is contained in:
parent
5e18e44037
commit
5b99a56fde
|
@ -139,13 +139,15 @@ func (c *Communicator) Connect(o terraform.UIOutput) (err error) {
|
|||
" Private key: %t\n"+
|
||||
" Certificate: %t\n"+
|
||||
" SSH Agent: %t\n"+
|
||||
" Checking Host Key: %t",
|
||||
" Checking Host Key: %t\n"+
|
||||
" Target Platform: %s\n",
|
||||
c.connInfo.Host, c.connInfo.User,
|
||||
c.connInfo.Password != "",
|
||||
c.connInfo.PrivateKey != "",
|
||||
c.connInfo.Certificate != "",
|
||||
c.connInfo.Agent,
|
||||
c.connInfo.HostKey != "",
|
||||
c.connInfo.TargetPlatform,
|
||||
))
|
||||
|
||||
if c.connInfo.BastionHost != "" {
|
||||
|
@ -343,7 +345,7 @@ func (c *Communicator) Start(cmd *remote.Cmd) error {
|
|||
session.Stdout = cmd.Stdout
|
||||
session.Stderr = cmd.Stderr
|
||||
|
||||
if !c.config.noPty {
|
||||
if !c.config.noPty && c.connInfo.TargetPlatform != TargetPlatformWindows {
|
||||
// Request a PTY
|
||||
termModes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // do not echo
|
||||
|
@ -425,17 +427,17 @@ func (c *Communicator) UploadScript(path string, input io.Reader) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("Error reading script: %s", err)
|
||||
}
|
||||
|
||||
var script bytes.Buffer
|
||||
if string(prefix) != "#!" {
|
||||
|
||||
if string(prefix) != "#!" && c.connInfo.TargetPlatform != TargetPlatformWindows {
|
||||
script.WriteString(DefaultShebang)
|
||||
}
|
||||
|
||||
script.ReadFrom(reader)
|
||||
|
||||
if err := c.Upload(path, &script); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.connInfo.TargetPlatform != TargetPlatformWindows {
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd := &remote.Cmd{
|
||||
Command: fmt.Sprintf("chmod 0777 %s", path),
|
||||
|
@ -453,7 +455,7 @@ func (c *Communicator) UploadScript(path string, input io.Reader) error {
|
|||
"Error chmodding script file to 0777 in remote "+
|
||||
"machine %v: %s %s", err, stdout.String(), stderr.String())
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,20 @@ const (
|
|||
// DefaultPort is used if there is no port given
|
||||
DefaultPort = 22
|
||||
|
||||
// DefaultScriptPath is used as the path to copy the file to
|
||||
// for remote execution if not provided otherwise.
|
||||
DefaultScriptPath = "/tmp/terraform_%RAND%.sh"
|
||||
// DefaultUnixScriptPath is used as the path to copy the file to
|
||||
// for remote execution on unix if not provided otherwise.
|
||||
DefaultUnixScriptPath = "/tmp/terraform_%RAND%.sh"
|
||||
// DefaultWindowsScriptPath is used as the path to copy the file to
|
||||
// for remote execution on windows if not provided otherwise.
|
||||
DefaultWindowsScriptPath = "C:/windows/temp/terraform_%RAND%.cmd"
|
||||
|
||||
// DefaultTimeout is used if there is no timeout given
|
||||
DefaultTimeout = 5 * time.Minute
|
||||
|
||||
// TargetPlatformUnix used for cleaner code, and is used if no target platform has been specified
|
||||
TargetPlatformUnix = "unix"
|
||||
//TargetPlatformWindows used for cleaner code
|
||||
TargetPlatformWindows = "windows"
|
||||
)
|
||||
|
||||
// connectionInfo is decoded from the ConnInfo of the resource. These are the
|
||||
|
@ -52,6 +60,7 @@ type connectionInfo struct {
|
|||
Timeout string
|
||||
ScriptPath string `mapstructure:"script_path"`
|
||||
TimeoutVal time.Duration `mapstructure:"-"`
|
||||
TargetPlatform string `mapstructure:"target_platform"`
|
||||
|
||||
BastionUser string `mapstructure:"bastion_user"`
|
||||
BastionPassword string `mapstructure:"bastion_password"`
|
||||
|
@ -106,8 +115,19 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
if connInfo.Port == 0 {
|
||||
connInfo.Port = DefaultPort
|
||||
}
|
||||
if connInfo.ScriptPath == "" {
|
||||
connInfo.ScriptPath = DefaultScriptPath
|
||||
// Set default targetPlatform to unix if it's empty
|
||||
if connInfo.TargetPlatform == "" {
|
||||
connInfo.TargetPlatform = TargetPlatformUnix
|
||||
} else if connInfo.TargetPlatform != TargetPlatformUnix && connInfo.TargetPlatform != TargetPlatformWindows {
|
||||
return nil, fmt.Errorf("target_platform for provisioner has to be either %s or %s", TargetPlatformUnix, TargetPlatformWindows)
|
||||
}
|
||||
// Choose an appropriate default script path based on the target platform. There is no single
|
||||
// suitable default script path which works on both UNIX and Windows targets.
|
||||
if connInfo.ScriptPath == "" && connInfo.TargetPlatform == TargetPlatformUnix {
|
||||
connInfo.ScriptPath = DefaultUnixScriptPath
|
||||
}
|
||||
if connInfo.ScriptPath == "" && connInfo.TargetPlatform == TargetPlatformWindows {
|
||||
connInfo.ScriptPath = DefaultWindowsScriptPath
|
||||
}
|
||||
if connInfo.Timeout != "" {
|
||||
connInfo.TimeoutVal = safeDuration(connInfo.Timeout, DefaultTimeout)
|
||||
|
|
|
@ -50,7 +50,10 @@ func TestProvisioner_connInfo(t *testing.T) {
|
|||
if conf.Timeout != "30s" {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
if conf.ScriptPath != DefaultScriptPath {
|
||||
if conf.ScriptPath != DefaultUnixScriptPath {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
if conf.TargetPlatform != TargetPlatformUnix {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
if conf.BastionHost != "127.0.1.1" {
|
||||
|
|
|
@ -161,8 +161,11 @@ var connectionBlockSupersetSchema = &configschema.Block{
|
|||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
// For type=ssh only (enforced in ssh communicator)
|
||||
"target_platform": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"private_key": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
|
|
|
@ -123,6 +123,9 @@ block would create a dependency cycle.
|
|||
|
||||
* `host_key` - The public key from the remote host or the signing CA, used to
|
||||
verify the connection.
|
||||
* `target_platform` - The target platform to connect to. Valid values are `windows` and `unix`. Defaults to `unix` if not set.
|
||||
|
||||
If the platform is set to `windows`, the default `script_path` is `c:\windows\temp\terraform_%RAND%.cmd`, assuming [the SSH default shell](https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_server_configuration#configuring-the-default-shell-for-openssh-in-windows) is `cmd.exe`. If the SSH default shell is PowerShell, set `script_path` to `"c:/windows/temp/terraform_%RAND%.ps1"`
|
||||
|
||||
**Additional arguments only supported by the `winrm` connection type:**
|
||||
|
||||
|
|
Loading…
Reference in New Issue