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 }