github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/communicator/winrm/communicator_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package winrm
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"regexp"
    10  	"strconv"
    11  	"testing"
    12  
    13  	"github.com/dylanmei/winrmtest"
    14  	"github.com/terramate-io/tf/communicator/remote"
    15  	"github.com/terramate-io/tf/communicator/shared"
    16  	"github.com/zclconf/go-cty/cty"
    17  )
    18  
    19  func newMockWinRMServer(t *testing.T) *winrmtest.Remote {
    20  	wrm := winrmtest.NewRemote()
    21  
    22  	wrm.CommandFunc(
    23  		winrmtest.MatchText("echo foo"),
    24  		func(out, err io.Writer) int {
    25  			out.Write([]byte("foo"))
    26  			return 0
    27  		})
    28  
    29  	wrm.CommandFunc(
    30  		winrmtest.MatchPattern(`^echo c29tZXRoaW5n >> ".*"$`),
    31  		func(out, err io.Writer) int {
    32  			return 0
    33  		})
    34  
    35  	wrm.CommandFunc(
    36  		winrmtest.MatchPattern(`^powershell.exe -EncodedCommand .*$`),
    37  		func(out, err io.Writer) int {
    38  			return 0
    39  		})
    40  
    41  	wrm.CommandFunc(
    42  		winrmtest.MatchText("powershell"),
    43  		func(out, err io.Writer) int {
    44  			return 0
    45  		})
    46  
    47  	return wrm
    48  }
    49  
    50  func TestStart(t *testing.T) {
    51  	wrm := newMockWinRMServer(t)
    52  	defer wrm.Close()
    53  
    54  	v := cty.ObjectVal(map[string]cty.Value{
    55  		"type":     cty.StringVal("winrm"),
    56  		"user":     cty.StringVal("user"),
    57  		"password": cty.StringVal("pass"),
    58  		"host":     cty.StringVal(wrm.Host),
    59  		"port":     cty.StringVal(strconv.Itoa(wrm.Port)),
    60  		"timeout":  cty.StringVal("30s"),
    61  	})
    62  
    63  	c, err := New(v)
    64  	if err != nil {
    65  		t.Fatalf("error creating communicator: %s", err)
    66  	}
    67  
    68  	var cmd remote.Cmd
    69  	stdout := new(bytes.Buffer)
    70  	cmd.Command = "echo foo"
    71  	cmd.Stdout = stdout
    72  
    73  	err = c.Start(&cmd)
    74  	if err != nil {
    75  		t.Fatalf("error executing remote command: %s", err)
    76  	}
    77  	cmd.Wait()
    78  
    79  	if stdout.String() != "foo" {
    80  		t.Fatalf("bad command response: expected %q, got %q", "foo", stdout.String())
    81  	}
    82  }
    83  
    84  func TestUpload(t *testing.T) {
    85  	wrm := newMockWinRMServer(t)
    86  	defer wrm.Close()
    87  	v := cty.ObjectVal(map[string]cty.Value{
    88  		"type":     cty.StringVal("winrm"),
    89  		"user":     cty.StringVal("user"),
    90  		"password": cty.StringVal("pass"),
    91  		"host":     cty.StringVal(wrm.Host),
    92  		"port":     cty.StringVal(strconv.Itoa(wrm.Port)),
    93  		"timeout":  cty.StringVal("30s"),
    94  	})
    95  
    96  	c, err := New(v)
    97  	if err != nil {
    98  		t.Fatalf("error creating communicator: %s", err)
    99  	}
   100  
   101  	err = c.Connect(nil)
   102  	if err != nil {
   103  		t.Fatalf("error connecting communicator: %s", err)
   104  	}
   105  	defer c.Disconnect()
   106  
   107  	err = c.Upload("C:/Temp/terraform.cmd", bytes.NewReader([]byte("something")))
   108  	if err != nil {
   109  		t.Fatalf("error uploading file: %s", err)
   110  	}
   111  }
   112  
   113  func TestScriptPath(t *testing.T) {
   114  	cases := []struct {
   115  		Input   string
   116  		Pattern string
   117  	}{
   118  		{
   119  			"/tmp/script.sh",
   120  			`^/tmp/script\.sh$`,
   121  		},
   122  		{
   123  			"/tmp/script_%RAND%.sh",
   124  			`^/tmp/script_(\d+)\.sh$`,
   125  		},
   126  	}
   127  
   128  	for _, tc := range cases {
   129  		v := cty.ObjectVal(map[string]cty.Value{
   130  			"host":        cty.StringVal(""),
   131  			"type":        cty.StringVal("winrm"),
   132  			"script_path": cty.StringVal(tc.Input),
   133  		})
   134  
   135  		comm, err := New(v)
   136  		if err != nil {
   137  			t.Fatalf("err: %s", err)
   138  		}
   139  		output := comm.ScriptPath()
   140  
   141  		match, err := regexp.Match(tc.Pattern, []byte(output))
   142  		if err != nil {
   143  			t.Fatalf("bad: %s\n\nerr: %s", tc.Input, err)
   144  		}
   145  		if !match {
   146  			t.Fatalf("bad: %s\n\n%s", tc.Input, output)
   147  		}
   148  	}
   149  }
   150  
   151  func TestNoTransportDecorator(t *testing.T) {
   152  	wrm := newMockWinRMServer(t)
   153  	defer wrm.Close()
   154  	v := cty.ObjectVal(map[string]cty.Value{
   155  		"type":     cty.StringVal("winrm"),
   156  		"user":     cty.StringVal("user"),
   157  		"password": cty.StringVal("pass"),
   158  		"host":     cty.StringVal(wrm.Host),
   159  		"port":     cty.StringVal(strconv.Itoa(wrm.Port)),
   160  		"timeout":  cty.StringVal("30s"),
   161  	})
   162  
   163  	c, err := New(v)
   164  	if err != nil {
   165  		t.Fatalf("error creating communicator: %s", err)
   166  	}
   167  
   168  	err = c.Connect(nil)
   169  	if err != nil {
   170  		t.Fatalf("error connecting communicator: %s", err)
   171  	}
   172  	defer c.Disconnect()
   173  
   174  	if c.client.TransportDecorator != nil {
   175  		t.Fatal("bad TransportDecorator: expected nil, got non-nil")
   176  	}
   177  }
   178  
   179  func TestTransportDecorator(t *testing.T) {
   180  	wrm := newMockWinRMServer(t)
   181  	defer wrm.Close()
   182  
   183  	v := cty.ObjectVal(map[string]cty.Value{
   184  		"type":     cty.StringVal("winrm"),
   185  		"user":     cty.StringVal("user"),
   186  		"password": cty.StringVal("pass"),
   187  		"host":     cty.StringVal(wrm.Host),
   188  		"port":     cty.StringVal(strconv.Itoa(wrm.Port)),
   189  		"use_ntlm": cty.StringVal("true"),
   190  		"timeout":  cty.StringVal("30s"),
   191  	})
   192  
   193  	c, err := New(v)
   194  	if err != nil {
   195  		t.Fatalf("error creating communicator: %s", err)
   196  	}
   197  
   198  	err = c.Connect(nil)
   199  	if err != nil {
   200  		t.Fatalf("error connecting communicator: %s", err)
   201  	}
   202  	defer c.Disconnect()
   203  
   204  	if c.client.TransportDecorator == nil {
   205  		t.Fatal("bad TransportDecorator: expected non-nil, got nil")
   206  	}
   207  }
   208  
   209  func TestScriptPath_randSeed(t *testing.T) {
   210  	// Pre GH-4186 fix, this value was the deterministic start the pseudorandom
   211  	// chain of unseeded math/rand values for Int31().
   212  	staticSeedPath := "C:/Temp/terraform_1298498081.cmd"
   213  	c, err := New(cty.NullVal(shared.ConnectionBlockSupersetSchema.ImpliedType()))
   214  	if err != nil {
   215  		t.Fatalf("err: %s", err)
   216  	}
   217  	path := c.ScriptPath()
   218  	if path == staticSeedPath {
   219  		t.Fatalf("rand not seeded! got: %s", path)
   220  	}
   221  }