| package winrm |
| |
| import ( |
| "bytes" |
| "io" |
| "regexp" |
| "strconv" |
| "testing" |
| |
| "github.com/dylanmei/winrmtest" |
| "github.com/hashicorp/terraform/internal/communicator/remote" |
| "github.com/hashicorp/terraform/internal/communicator/shared" |
| "github.com/zclconf/go-cty/cty" |
| ) |
| |
| func newMockWinRMServer(t *testing.T) *winrmtest.Remote { |
| wrm := winrmtest.NewRemote() |
| |
| wrm.CommandFunc( |
| winrmtest.MatchText("echo foo"), |
| func(out, err io.Writer) int { |
| out.Write([]byte("foo")) |
| return 0 |
| }) |
| |
| wrm.CommandFunc( |
| winrmtest.MatchPattern(`^echo c29tZXRoaW5n >> ".*"$`), |
| func(out, err io.Writer) int { |
| return 0 |
| }) |
| |
| wrm.CommandFunc( |
| winrmtest.MatchPattern(`^powershell.exe -EncodedCommand .*$`), |
| func(out, err io.Writer) int { |
| return 0 |
| }) |
| |
| wrm.CommandFunc( |
| winrmtest.MatchText("powershell"), |
| func(out, err io.Writer) int { |
| return 0 |
| }) |
| |
| return wrm |
| } |
| |
| func TestStart(t *testing.T) { |
| wrm := newMockWinRMServer(t) |
| defer wrm.Close() |
| |
| v := cty.ObjectVal(map[string]cty.Value{ |
| "type": cty.StringVal("winrm"), |
| "user": cty.StringVal("user"), |
| "password": cty.StringVal("pass"), |
| "host": cty.StringVal(wrm.Host), |
| "port": cty.StringVal(strconv.Itoa(wrm.Port)), |
| "timeout": cty.StringVal("30s"), |
| }) |
| |
| c, err := New(v) |
| if err != nil { |
| t.Fatalf("error creating communicator: %s", err) |
| } |
| |
| var cmd remote.Cmd |
| stdout := new(bytes.Buffer) |
| cmd.Command = "echo foo" |
| cmd.Stdout = stdout |
| |
| err = c.Start(&cmd) |
| if err != nil { |
| t.Fatalf("error executing remote command: %s", err) |
| } |
| cmd.Wait() |
| |
| if stdout.String() != "foo" { |
| t.Fatalf("bad command response: expected %q, got %q", "foo", stdout.String()) |
| } |
| } |
| |
| func TestUpload(t *testing.T) { |
| wrm := newMockWinRMServer(t) |
| defer wrm.Close() |
| v := cty.ObjectVal(map[string]cty.Value{ |
| "type": cty.StringVal("winrm"), |
| "user": cty.StringVal("user"), |
| "password": cty.StringVal("pass"), |
| "host": cty.StringVal(wrm.Host), |
| "port": cty.StringVal(strconv.Itoa(wrm.Port)), |
| "timeout": cty.StringVal("30s"), |
| }) |
| |
| c, err := New(v) |
| if err != nil { |
| t.Fatalf("error creating communicator: %s", err) |
| } |
| |
| err = c.Connect(nil) |
| if err != nil { |
| t.Fatalf("error connecting communicator: %s", err) |
| } |
| defer c.Disconnect() |
| |
| err = c.Upload("C:/Temp/terraform.cmd", bytes.NewReader([]byte("something"))) |
| if err != nil { |
| t.Fatalf("error uploading file: %s", err) |
| } |
| } |
| |
| func TestScriptPath(t *testing.T) { |
| cases := []struct { |
| Input string |
| Pattern string |
| }{ |
| { |
| "/tmp/script.sh", |
| `^/tmp/script\.sh$`, |
| }, |
| { |
| "/tmp/script_%RAND%.sh", |
| `^/tmp/script_(\d+)\.sh$`, |
| }, |
| } |
| |
| for _, tc := range cases { |
| v := cty.ObjectVal(map[string]cty.Value{ |
| "host": cty.StringVal(""), |
| "type": cty.StringVal("winrm"), |
| "script_path": cty.StringVal(tc.Input), |
| }) |
| |
| comm, err := New(v) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| output := comm.ScriptPath() |
| |
| match, err := regexp.Match(tc.Pattern, []byte(output)) |
| if err != nil { |
| t.Fatalf("bad: %s\n\nerr: %s", tc.Input, err) |
| } |
| if !match { |
| t.Fatalf("bad: %s\n\n%s", tc.Input, output) |
| } |
| } |
| } |
| |
| func TestNoTransportDecorator(t *testing.T) { |
| wrm := newMockWinRMServer(t) |
| defer wrm.Close() |
| v := cty.ObjectVal(map[string]cty.Value{ |
| "type": cty.StringVal("winrm"), |
| "user": cty.StringVal("user"), |
| "password": cty.StringVal("pass"), |
| "host": cty.StringVal(wrm.Host), |
| "port": cty.StringVal(strconv.Itoa(wrm.Port)), |
| "timeout": cty.StringVal("30s"), |
| }) |
| |
| c, err := New(v) |
| if err != nil { |
| t.Fatalf("error creating communicator: %s", err) |
| } |
| |
| err = c.Connect(nil) |
| if err != nil { |
| t.Fatalf("error connecting communicator: %s", err) |
| } |
| defer c.Disconnect() |
| |
| if c.client.TransportDecorator != nil { |
| t.Fatal("bad TransportDecorator: expected nil, got non-nil") |
| } |
| } |
| |
| func TestTransportDecorator(t *testing.T) { |
| wrm := newMockWinRMServer(t) |
| defer wrm.Close() |
| |
| v := cty.ObjectVal(map[string]cty.Value{ |
| "type": cty.StringVal("winrm"), |
| "user": cty.StringVal("user"), |
| "password": cty.StringVal("pass"), |
| "host": cty.StringVal(wrm.Host), |
| "port": cty.StringVal(strconv.Itoa(wrm.Port)), |
| "use_ntlm": cty.StringVal("true"), |
| "timeout": cty.StringVal("30s"), |
| }) |
| |
| c, err := New(v) |
| if err != nil { |
| t.Fatalf("error creating communicator: %s", err) |
| } |
| |
| err = c.Connect(nil) |
| if err != nil { |
| t.Fatalf("error connecting communicator: %s", err) |
| } |
| defer c.Disconnect() |
| |
| if c.client.TransportDecorator == nil { |
| t.Fatal("bad TransportDecorator: expected non-nil, got nil") |
| } |
| } |
| |
| func TestScriptPath_randSeed(t *testing.T) { |
| // Pre GH-4186 fix, this value was the deterministic start the pseudorandom |
| // chain of unseeded math/rand values for Int31(). |
| staticSeedPath := "C:/Temp/terraform_1298498081.cmd" |
| c, err := New(cty.NullVal(shared.ConnectionBlockSupersetSchema.ImpliedType())) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| path := c.ScriptPath() |
| if path == staticSeedPath { |
| t.Fatalf("rand not seeded! got: %s", path) |
| } |
| } |