diff --git a/command.go b/command.go
index f7c3551..7aa2e5e 100644
--- a/command.go
+++ b/command.go
@@ -201,6 +201,11 @@ func (c *Command) ExitCode() int {
return c.exitCode
}
+// Error returns command execution error if any
+func (c *Command) Error() error {
+ return c.err
+}
+
// Wait function will block the current goroutine until the remote command terminates.
func (c *Command) Wait() {
// block until finished
diff --git a/fixture_test.go b/fixture_test.go
index 058e7c9..122f151 100644
--- a/fixture_test.go
+++ b/fixture_test.go
@@ -49,6 +49,40 @@ var (
`
+ createShellResponseWithError = `
+
+ http://schemas.dmtf.org/wbem/wsman/1/wsman/fault
+ uuid:0A888267-33ED-4F08-98E6-DDEBDE2067DE
+ http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
+ uuid:1893210b-91a7-45dc-aa90-b0c42e0dd740
+
+
+
+
+ s:Receiver
+ w:InternalError
+
+
+ Illegal operation attempted on a registry key that has been marked for deletion.
+
+
+
+
+ Illegal operation attempted on a registry key that has been marked for deletion.
+
+
+
+
+
+ `
+
executeCommandResponse = `http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandResponseuuid:D9E108AA-E32B-45E3-8601-E9C70999D3BAhttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousuuid:F530804C-6D02-4FA9-AE78-1997750594BA1A6DEE6B-EC68-4DD6-87E9-030C0048ECC4`
executeCommandResponseWithError = `http://schemas.dmtf.org/wbem/wsman/1/wsman/faultuuid:C85E435B-712E-45E8-AC64-C53F9FEE7164http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousuuid:23d79ab4-f145-4ac5-baa3-084d67265a24s:Receiverw:InternalErrorThe filename or extension is too long. The filename or extension is too long. `
diff --git a/response.go b/response.go
index 792ead5..028cdcb 100644
--- a/response.go
+++ b/response.go
@@ -66,45 +66,48 @@ func xPath(node tree.Node, xpath string) (tree.NodeSet, error) {
return nodes, nil
}
-// ParseOpenShellResponse ParseOpenShellResponse
-func ParseOpenShellResponse(response string) (string, error) {
- doc, err := xmltree.ParseXML(strings.NewReader(response))
- if err != nil {
- return "", err
- }
- return first(doc, "//w:Selector[@Name='ShellId']")
+func newExecuteCommandError(response string, format string, args ...interface{}) *ExecuteCommandError {
+ return &ExecuteCommandError{fmt.Errorf(format, args...), response}
}
-// ParseExecuteCommandResponse ParseExecuteCommandResponse
-func ParseExecuteCommandResponse(response string) (commandId string, err error) {
- defer func() {
- if err != nil {
- err = &ExecuteCommandError{Inner: err, Body: response}
- }
- }()
-
+func parseResponse(response, expectedAction, idXPath string) (string, error) {
doc, err := xmltree.ParseXML(strings.NewReader(response))
if err != nil {
- return "", fmt.Errorf("parsing xml response: %w", err)
+ return "", newExecuteCommandError(response, "parsing xml response: %w", err)
}
action, err := first(doc, "//a:Action")
if err != nil {
- return "", fmt.Errorf("getting response action: %w", err)
+ return "", newExecuteCommandError(response, "getting response action: %w", err)
}
- switch action {
- case "http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandResponse":
- commandId, err = first(doc, "//rsp:CommandId")
+ if action == "http://schemas.dmtf.org/wbem/wsman/1/wsman/fault" {
+ return "", newExecuteCommandError(response, "received error response")
+ }
+ if action == expectedAction {
+ id, err := first(doc, idXPath)
if err != nil {
- return "", fmt.Errorf("finding command id: %w", err)
+ return "", newExecuteCommandError(response, "finding %v: %w", idXPath, err)
}
+ return id, nil
+ }
+ return "", newExecuteCommandError(response, "unsupported action: %v", action)
+}
- return commandId, nil
+func ParseOpenShellResponse(response string) (string, error) {
+ return parseResponse(
+ response,
+ "http://schemas.xmlsoap.org/ws/2004/09/transfer/CreateResponse",
+ "//rsp:ShellId",
+ )
+}
- default:
- return "", fmt.Errorf("unsupported action: %v", action)
- }
+func ParseExecuteCommandResponse(response string) (string, error) {
+ return parseResponse(
+ response,
+ "http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandResponse",
+ "//rsp:CommandId",
+ )
}
// ParseSlurpOutputErrResponse ParseSlurpOutputErrResponse
diff --git a/response_test.go b/response_test.go
index 8be28c5..ff3842e 100644
--- a/response_test.go
+++ b/response_test.go
@@ -17,6 +17,20 @@ func (s *WinRMSuite) TestOpenShellResponse(c *C) {
c.Assert("67A74734-DD32-4F10-89DE-49A060483810", Equals, shellID)
}
+func (s *WinRMSuite) TestOpenShellResponseError(c *C) {
+ response := createShellResponseWithError
+ shellId, err := ParseOpenShellResponse(response)
+ if err == nil {
+ c.Fatal("expected error")
+ }
+ c.Assert(shellId, Equals, "")
+
+ var execCmdRespErr *ExecuteCommandError
+ if !errors.As(err, &execCmdRespErr) {
+ c.Fatal("expected err to be of type ExecuteCommandError")
+ }
+}
+
func (s *WinRMSuite) TestExecuteCommandResponse(c *C) {
response := executeCommandResponse