winrm 1.8.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -11
  3. data/.rubocop.yml +26 -22
  4. data/.travis.yml +11 -12
  5. data/Gemfile +3 -9
  6. data/LICENSE +202 -202
  7. data/README.md +232 -215
  8. data/Rakefile +34 -36
  9. data/Vagrantfile +6 -9
  10. data/WinrmAppveyor.psm1 +31 -31
  11. data/appveyor.yml +51 -51
  12. data/bin/rwinrm +97 -97
  13. data/changelog.md +86 -86
  14. data/lib/winrm.rb +39 -42
  15. data/lib/winrm/connection.rb +82 -0
  16. data/lib/winrm/connection_opts.rb +87 -0
  17. data/lib/winrm/{exceptions/exceptions.rb → exceptions.rb} +76 -57
  18. data/lib/winrm/http/response_handler.rb +96 -82
  19. data/lib/winrm/http/transport.rb +424 -435
  20. data/lib/winrm/http/transport_factory.rb +68 -0
  21. data/lib/winrm/output.rb +59 -43
  22. data/lib/winrm/psrp/create_pipeline.xml.erb +167 -0
  23. data/lib/winrm/psrp/fragment.rb +70 -0
  24. data/lib/winrm/psrp/init_runspace_pool.xml.erb +224 -0
  25. data/lib/winrm/psrp/message.rb +130 -0
  26. data/lib/winrm/psrp/message_data.rb +41 -0
  27. data/lib/winrm/psrp/message_data/base.rb +49 -0
  28. data/lib/winrm/psrp/message_data/error_record.rb +68 -0
  29. data/lib/winrm/psrp/message_data/pipeline_host_call.rb +32 -0
  30. data/lib/winrm/psrp/message_data/pipeline_output.rb +49 -0
  31. data/lib/winrm/psrp/message_data/runspacepool_host_call.rb +32 -0
  32. data/lib/winrm/psrp/message_data/runspacepool_state.rb +39 -0
  33. data/lib/winrm/psrp/message_data/session_capability.rb +36 -0
  34. data/lib/winrm/psrp/message_defragmenter.rb +62 -0
  35. data/lib/winrm/psrp/message_factory.rb +75 -0
  36. data/lib/winrm/psrp/message_fragmenter.rb +60 -0
  37. data/lib/winrm/psrp/powershell_output_decoder.rb +120 -0
  38. data/lib/winrm/psrp/receive_response_reader.rb +93 -0
  39. data/lib/winrm/psrp/session_capability.xml.erb +7 -0
  40. data/lib/winrm/psrp/uuid.rb +40 -0
  41. data/lib/winrm/shells/base.rb +175 -0
  42. data/lib/winrm/shells/cmd.rb +65 -0
  43. data/lib/winrm/shells/power_shell.rb +201 -0
  44. data/lib/winrm/shells/retryable.rb +45 -0
  45. data/lib/winrm/shells/shell_factory.rb +50 -0
  46. data/lib/winrm/version.rb +7 -7
  47. data/lib/winrm/wsmv/base.rb +59 -0
  48. data/lib/winrm/wsmv/cleanup_command.rb +61 -0
  49. data/lib/winrm/wsmv/close_shell.rb +50 -0
  50. data/lib/winrm/wsmv/command.rb +101 -0
  51. data/lib/winrm/wsmv/command_output.rb +76 -0
  52. data/lib/winrm/wsmv/command_output_decoder.rb +55 -0
  53. data/lib/winrm/wsmv/configuration.rb +46 -0
  54. data/lib/winrm/wsmv/create_pipeline.rb +66 -0
  55. data/lib/winrm/wsmv/create_shell.rb +119 -0
  56. data/lib/winrm/wsmv/header.rb +203 -0
  57. data/lib/winrm/wsmv/init_runspace_pool.rb +95 -0
  58. data/lib/winrm/wsmv/iso8601_duration.rb +60 -0
  59. data/lib/winrm/wsmv/keep_alive.rb +68 -0
  60. data/lib/winrm/wsmv/receive_response_reader.rb +128 -0
  61. data/lib/winrm/wsmv/send_data.rb +68 -0
  62. data/lib/winrm/wsmv/soap.rb +51 -0
  63. data/lib/winrm/wsmv/wql_query.rb +79 -0
  64. data/lib/winrm/wsmv/write_stdin.rb +88 -0
  65. data/preamble +17 -17
  66. data/{spec → tests/integration}/auth_timeout_spec.rb +18 -16
  67. data/{spec → tests/integration}/cmd_spec.rb +104 -102
  68. data/{spec → tests/integration}/config-example.yml +16 -19
  69. data/{spec → tests/integration}/issue_59_spec.rb +26 -23
  70. data/tests/integration/powershell_spec.rb +154 -0
  71. data/{spec → tests/integration}/spec_helper.rb +65 -73
  72. data/{spec → tests/integration}/transport_spec.rb +99 -139
  73. data/{spec → tests/integration}/wql_spec.rb +16 -14
  74. data/{spec → tests}/matchers.rb +60 -74
  75. data/tests/spec/configuration_spec.rb +93 -0
  76. data/tests/spec/connection_spec.rb +39 -0
  77. data/{spec → tests/spec}/exception_spec.rb +50 -50
  78. data/tests/spec/http/transport_factory_spec.rb +68 -0
  79. data/tests/spec/http/transport_spec.rb +44 -0
  80. data/{spec → tests/spec}/output_spec.rb +127 -110
  81. data/tests/spec/psrp/fragment_spec.rb +62 -0
  82. data/tests/spec/psrp/message_data/base_spec.rb +13 -0
  83. data/tests/spec/psrp/message_data/error_record_spec.rb +41 -0
  84. data/tests/spec/psrp/message_data/pipeline_host_call_spec.rb +25 -0
  85. data/tests/spec/psrp/message_data/pipeline_output_spec.rb +32 -0
  86. data/tests/spec/psrp/message_data/runspace_pool_host_call_spec.rb +25 -0
  87. data/tests/spec/psrp/message_data/runspacepool_state_spec.rb +16 -0
  88. data/tests/spec/psrp/message_data/session_capability_spec.rb +30 -0
  89. data/tests/spec/psrp/message_data_spec.rb +35 -0
  90. data/tests/spec/psrp/message_defragmenter_spec.rb +47 -0
  91. data/tests/spec/psrp/message_fragmenter_spec.rb +105 -0
  92. data/tests/spec/psrp/powershell_output_decoder_spec.rb +84 -0
  93. data/tests/spec/psrp/psrp_message_spec.rb +70 -0
  94. data/tests/spec/psrp/recieve_response_reader_spec.rb +154 -0
  95. data/tests/spec/psrp/uuid_spec.rb +28 -0
  96. data/{spec → tests/spec}/response_handler_spec.rb +61 -61
  97. data/tests/spec/shells/base_spec.rb +202 -0
  98. data/tests/spec/shells/cmd_spec.rb +75 -0
  99. data/tests/spec/shells/powershell_spec.rb +175 -0
  100. data/tests/spec/spec_helper.rb +47 -0
  101. data/tests/spec/stubs/clixml/error_record.xml.erb +84 -0
  102. data/{spec → tests/spec}/stubs/responses/get_command_output_response.xml.erb +13 -13
  103. data/tests/spec/stubs/responses/get_command_output_response_not_done.xml.erb +10 -0
  104. data/tests/spec/stubs/responses/get_powershell_keepalive_response.xml.erb +10 -0
  105. data/tests/spec/stubs/responses/get_powershell_output_response.xml.erb +12 -0
  106. data/tests/spec/stubs/responses/get_powershell_output_response_not_done.xml.erb +9 -0
  107. data/{spec → tests/spec}/stubs/responses/open_shell_v1.xml +19 -19
  108. data/{spec → tests/spec}/stubs/responses/open_shell_v2.xml +20 -20
  109. data/{spec → tests/spec}/stubs/responses/soap_fault_v1.xml +36 -36
  110. data/{spec → tests/spec}/stubs/responses/soap_fault_v2.xml +42 -42
  111. data/{spec → tests/spec}/stubs/responses/wmi_error_v2.xml +41 -41
  112. data/tests/spec/wsmv/cleanup_command_spec.rb +22 -0
  113. data/tests/spec/wsmv/close_shell_spec.rb +17 -0
  114. data/{spec → tests/spec/wsmv}/command_output_decoder_spec.rb +37 -37
  115. data/tests/spec/wsmv/command_output_spec.rb +45 -0
  116. data/tests/spec/wsmv/command_spec.rb +19 -0
  117. data/tests/spec/wsmv/configuration_spec.rb +17 -0
  118. data/tests/spec/wsmv/create_pipeline_spec.rb +31 -0
  119. data/tests/spec/wsmv/create_shell_spec.rb +38 -0
  120. data/tests/spec/wsmv/init_runspace_pool_spec.rb +36 -0
  121. data/tests/spec/wsmv/keep_alive_spec.rb +21 -0
  122. data/tests/spec/wsmv/receive_response_reader_spec.rb +123 -0
  123. data/tests/spec/wsmv/send_data_spec.rb +30 -0
  124. data/tests/spec/wsmv/wql_query_spec.rb +13 -0
  125. data/tests/spec/wsmv/write_stdin_spec.rb +22 -0
  126. data/winrm.gemspec +42 -40
  127. metadata +140 -38
  128. data/.rspec +0 -3
  129. data/lib/winrm/command_executor.rb +0 -243
  130. data/lib/winrm/command_output_decoder.rb +0 -53
  131. data/lib/winrm/helpers/iso8601_duration.rb +0 -58
  132. data/lib/winrm/helpers/powershell_script.rb +0 -42
  133. data/lib/winrm/soap_provider.rb +0 -39
  134. data/lib/winrm/winrm_service.rb +0 -550
  135. data/spec/command_executor_spec.rb +0 -475
  136. data/spec/issue_184_spec.rb +0 -67
  137. data/spec/powershell_spec.rb +0 -97
  138. data/spec/winrm_options_spec.rb +0 -76
  139. data/spec/winrm_primitives_spec.rb +0 -51
@@ -1,42 +1,39 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2010 Dan Wanek <dan.wanek@gmail.com>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'date'
18
- require 'logging'
19
- require_relative 'winrm/version'
20
-
21
- # Main WinRM module entry point
22
- module WinRM
23
- # Enable logging if it is requested. We do this before
24
- # anything else so that we can setup the output before
25
- # any logging occurs.
26
- if ENV['WINRM_LOG'] && ENV['WINRM_LOG'] != ''
27
- begin
28
- Logging.logger.root.level = ENV['WINRM_LOG']
29
- Logging.logger.root.appenders = Logging.appenders.stderr
30
- rescue ArgumentError
31
- # This means that the logging level wasn't valid
32
- $stderr.puts "Invalid WINRM_LOG level is set: #{ENV['WINRM_LOG']}"
33
- $stderr.puts ''
34
- $stderr.puts 'Please use one of the standard log levels: ' \
35
- 'debug, info, warn, or error'
36
- end
37
- end
38
- end
39
-
40
- require 'winrm/output'
41
- require 'winrm/helpers/iso8601_duration'
42
- require 'winrm/soap_provider'
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2010 Dan Wanek <dan.wanek@gmail.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'logging'
18
+ require_relative 'winrm/version'
19
+ require_relative 'winrm/connection'
20
+ require_relative 'winrm/exceptions'
21
+
22
+ # Main WinRM module entry point
23
+ module WinRM
24
+ # Enable logging if it is requested. We do this before
25
+ # anything else so that we can setup the output before
26
+ # any logging occurs.
27
+ if ENV['WINRM_LOG'] && ENV['WINRM_LOG'] != ''
28
+ begin
29
+ Logging.logger.root.level = ENV['WINRM_LOG']
30
+ Logging.logger.root.appenders = Logging.appenders.stderr
31
+ rescue ArgumentError
32
+ # This means that the logging level wasn't valid
33
+ $stderr.puts "Invalid WINRM_LOG level is set: #{ENV['WINRM_LOG']}"
34
+ $stderr.puts ''
35
+ $stderr.puts 'Please use one of the standard log levels: ' \
36
+ 'debug, info, warn, or error'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,82 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require_relative 'connection_opts'
18
+ require_relative 'http/transport_factory'
19
+ require_relative 'shells/shell_factory'
20
+ require_relative 'wsmv/wql_query'
21
+
22
+ module WinRM
23
+ # WinRM connection used to establish a session with the remote WinRM service.
24
+ class Connection
25
+ # Creates a new WinRM connection
26
+ # See the ConnectionOpts class for connection options.
27
+ def initialize(connection_opts)
28
+ configure_connection_opts(connection_opts)
29
+ configure_logger
30
+ end
31
+
32
+ attr_accessor :logger
33
+
34
+ # Creates a new shell on the remote Windows server associated with
35
+ # this connection.
36
+ # @param shell_type [Symbol] The shell type :cmd or :powershell
37
+ # @return [Shell] PowerShell or Cmd shell instance.
38
+ def shell(shell_type)
39
+ shell = shell_factory.create_shell(shell_type)
40
+ if block_given?
41
+ begin
42
+ yield shell
43
+ ensure
44
+ shell.close
45
+ end
46
+ else
47
+ shell
48
+ end
49
+ end
50
+
51
+ # Executes a WQL query against the WinRM connection
52
+ # @param wql [String] The wql query
53
+ # @return [Hash] Hash representation of wql query response
54
+ def run_wql(wql)
55
+ query = WinRM::WSMV::WqlQuery.new(@connection_opts, wql)
56
+ query.process_response(transport.send_request(query.build))
57
+ end
58
+
59
+ private
60
+
61
+ def configure_connection_opts(connection_opts)
62
+ @connection_opts = ConnectionOpts.create_with_defaults(connection_opts)
63
+ end
64
+
65
+ def configure_logger
66
+ @logger = Logging.logger[self]
67
+ logger.level = :warn
68
+ logger.add_appenders(Logging.appenders.stdout)
69
+ end
70
+
71
+ def shell_factory
72
+ @shell_factory ||= WinRM::Shells::ShellFactory.new(@connection_opts, transport, logger)
73
+ end
74
+
75
+ def transport
76
+ @transport ||= begin
77
+ transport_factory = WinRM::HTTP::TransportFactory.new
78
+ transport_factory.create_transport(@connection_opts)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,87 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Copyright 2016 Shawn Neal <sneal@sneal.net>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'securerandom'
18
+
19
+ module WinRM
20
+ # WinRM connection options, provides defaults and validation.
21
+ class ConnectionOpts < Hash
22
+ DEFAULT_OPERATION_TIMEOUT = 60
23
+ DEFAULT_RECEIVE_TIMEOUT = DEFAULT_OPERATION_TIMEOUT + 10
24
+ DEFAULT_MAX_ENV_SIZE = 153600
25
+ DEFAULT_LOCALE = 'en-US'.freeze
26
+ DEFAULT_RETRY_DELAY = 10
27
+ DEFAULT_RETRY_LIMIT = 3
28
+
29
+ class << self
30
+ def create_with_defaults(overrides)
31
+ config = default.merge(overrides)
32
+ config = ensure_receive_timeout_is_greater_than_operation_timeout(config)
33
+ config.validate
34
+ config
35
+ end
36
+
37
+ private
38
+
39
+ def ensure_receive_timeout_is_greater_than_operation_timeout(config)
40
+ if config[:receive_timeout] < config[:operation_timeout]
41
+ config[:receive_timeout] = config[:operation_timeout] + 10
42
+ end
43
+ config
44
+ end
45
+
46
+ def default
47
+ config = ConnectionOpts.new
48
+ config[:session_id] = SecureRandom.uuid.to_s.upcase
49
+ config[:transport] = :negotiate
50
+ config[:locale] = DEFAULT_LOCALE
51
+ config[:max_envelope_size] = DEFAULT_MAX_ENV_SIZE
52
+ config[:operation_timeout] = DEFAULT_OPERATION_TIMEOUT
53
+ config[:receive_timeout] = DEFAULT_RECEIVE_TIMEOUT
54
+ config[:retry_delay] = DEFAULT_RETRY_DELAY
55
+ config[:retry_limit] = DEFAULT_RETRY_LIMIT
56
+ config
57
+ end
58
+ end
59
+
60
+ def validate
61
+ validate_required_fields
62
+ validate_data_types
63
+ end
64
+
65
+ private
66
+
67
+ def validate_required_fields
68
+ raise 'endpoint is a required option' unless self[:endpoint]
69
+ raise 'user is a required option' unless self[:user]
70
+ raise 'password is a required option' unless self[:password]
71
+ end
72
+
73
+ def validate_data_types
74
+ validate_fixnum(:retry_limit)
75
+ validate_fixnum(:retry_delay)
76
+ validate_fixnum(:max_envelope_size)
77
+ validate_fixnum(:operation_timeout)
78
+ validate_fixnum(:receive_timeout, self[:operation_timeout])
79
+ end
80
+
81
+ def validate_fixnum(key, min = 0)
82
+ value = self[key]
83
+ raise "#{key} must be a Fixnum" unless value && value.is_a?(Fixnum)
84
+ raise "#{key} must be greater than #{min}" unless value > min
85
+ end
86
+ end
87
+ end
@@ -1,57 +1,76 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2010 Dan Wanek <dan.wanek@gmail.com>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- module WinRM
18
- # WinRM base class for errors
19
- class WinRMError < StandardError; end
20
-
21
- # Authorization Error
22
- class WinRMAuthorizationError < WinRMError; end
23
-
24
- # A Fault returned in the SOAP response. The XML node is a WSManFault
25
- class WinRMWSManFault < WinRMError
26
- attr_reader :fault_code
27
- attr_reader :fault_description
28
-
29
- def initialize(fault_description, fault_code)
30
- @fault_description = fault_description
31
- @fault_code = fault_code
32
- super("[WSMAN ERROR CODE: #{fault_code}]: #{fault_description}")
33
- end
34
- end
35
-
36
- # A Fault returned in the SOAP response. The XML node is a MSFT_WmiError
37
- class WinRMWMIError < WinRMError
38
- attr_reader :error_code
39
- attr_reader :error
40
-
41
- def initialize(error, error_code)
42
- @error = error
43
- @error_code = error_code
44
- super("[WMI ERROR CODE: #{error_code}]: #{error}")
45
- end
46
- end
47
-
48
- # non-200 response without a SOAP fault
49
- class WinRMHTTPTransportError < WinRMError
50
- attr_reader :status_code
51
-
52
- def initialize(msg, status_code)
53
- @status_code = status_code
54
- super(msg + " (#{status_code}).")
55
- end
56
- end
57
- end
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2010 Dan Wanek <dan.wanek@gmail.com>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module WinRM
18
+ # WinRM base class for errors
19
+ class WinRMError < StandardError; end
20
+
21
+ # Authorization Error
22
+ class WinRMAuthorizationError < WinRMError; end
23
+
24
+ # Shell creation error
25
+ class InvalidShellError < WinRMError; end
26
+
27
+ # Exitcode error
28
+ class InvalidExitCode < WinRMError; end
29
+
30
+ # Shell creation error
31
+ class InvalidTransportError < WinRMError
32
+ attr_reader :invalid_transport
33
+
34
+ def initialize(invalid_transport, valid_transports)
35
+ @invalid_transport = invalid_transport
36
+ super(
37
+ "Invalid transport '#{invalid_transport}' specified" \
38
+ ", expected: #{valid_transports.join(', ')}."
39
+ )
40
+ end
41
+ end
42
+
43
+ # A Fault returned in the SOAP response. The XML node is a WSManFault
44
+ class WinRMWSManFault < WinRMError
45
+ attr_reader :fault_code
46
+ attr_reader :fault_description
47
+
48
+ def initialize(fault_description, fault_code)
49
+ @fault_description = fault_description
50
+ @fault_code = fault_code
51
+ super("[WSMAN ERROR CODE: #{fault_code}]: #{fault_description}")
52
+ end
53
+ end
54
+
55
+ # A Fault returned in the SOAP response. The XML node is a MSFT_WmiError
56
+ class WinRMWMIError < WinRMError
57
+ attr_reader :error_code
58
+ attr_reader :error
59
+
60
+ def initialize(error, error_code)
61
+ @error = error
62
+ @error_code = error_code
63
+ super("[WMI ERROR CODE: #{error_code}]: #{error}")
64
+ end
65
+ end
66
+
67
+ # non-200 response without a SOAP fault
68
+ class WinRMHTTPTransportError < WinRMError
69
+ attr_reader :status_code
70
+
71
+ def initialize(msg, status_code = nil)
72
+ @status_code = status_code
73
+ super(msg + " (#{status_code}).")
74
+ end
75
+ end
76
+ end
@@ -1,82 +1,96 @@
1
- # encoding: UTF-8
2
- #
3
- # Copyright 2014 Shawn Neal <sneal@sneal.net>
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'rexml/document'
18
-
19
- module WinRM
20
- # Handles the raw WinRM HTTP response. Returns the body as an XML doc
21
- # or raises the appropriate WinRM error if the response is an error.
22
- class ResponseHandler
23
- # @param [String] The raw unparsed response body, if any
24
- # @param [Integer] The HTTP response status code
25
- def initialize(response_body, status_code)
26
- @response_body = response_body
27
- @status_code = status_code
28
- end
29
-
30
- # Processes the response from the WinRM service and either returns an XML
31
- # doc or raises an appropriate error.
32
- #
33
- # @returns [REXML::Document] The parsed response body
34
- def parse_to_xml
35
- raise_if_error
36
- response_xml
37
- end
38
-
39
- private
40
-
41
- def response_xml
42
- @response_xml ||= REXML::Document.new(@response_body)
43
- rescue REXML::ParseException => e
44
- raise WinRMHTTPTransportError.new(
45
- "Unable to parse WinRM response: #{e.message}", @status_code)
46
- end
47
-
48
- def raise_if_error
49
- return if @status_code == 200
50
- raise_if_auth_error
51
- raise_if_wsman_fault
52
- raise_if_wmi_error
53
- raise_transport_error
54
- end
55
-
56
- def raise_if_auth_error
57
- fail WinRMAuthorizationError if @status_code == 401
58
- end
59
-
60
- def raise_if_wsman_fault
61
- soap_errors = REXML::XPath.match(response_xml, "//#{NS_SOAP_ENV}:Body/#{NS_SOAP_ENV}:Fault/*")
62
- return if soap_errors.empty?
63
- fault = REXML::XPath.first(soap_errors, "//#{NS_WSMAN_FAULT}:WSManFault")
64
- fail WinRMWSManFault.new(fault.to_s, fault.attributes['Code']) unless fault.nil?
65
- end
66
-
67
- def raise_if_wmi_error
68
- soap_errors = REXML::XPath.match(response_xml, "//#{NS_SOAP_ENV}:Body/#{NS_SOAP_ENV}:Fault/*")
69
- return if soap_errors.empty?
70
-
71
- error = REXML::XPath.first(soap_errors, "//#{NS_WSMAN_MSFT}:MSFT_WmiError")
72
- return if error.nil?
73
-
74
- error_code = REXML::XPath.first(error, "//#{NS_WSMAN_MSFT}:error_Code").text
75
- fail WinRMWMIError.new(error.to_s, error_code)
76
- end
77
-
78
- def raise_transport_error
79
- fail WinRMHTTPTransportError.new('Bad HTTP response returned from server', @status_code)
80
- end
81
- end
82
- end
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2014 Shawn Neal <sneal@sneal.net>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'rexml/document'
18
+ require_relative '../wsmv/soap'
19
+
20
+ module WinRM
21
+ # Handles the raw WinRM HTTP response. Returns the body as an XML doc
22
+ # or raises the appropriate WinRM error if the response is an error.
23
+ class ResponseHandler
24
+ # @param [String] The raw unparsed response body, if any
25
+ # @param [Integer] The HTTP response status code
26
+ def initialize(response_body, status_code)
27
+ @response_body = response_body
28
+ @status_code = status_code
29
+ end
30
+
31
+ # Processes the response from the WinRM service and either returns an XML
32
+ # doc or raises an appropriate error.
33
+ #
34
+ # @returns [REXML::Document] The parsed response body
35
+ def parse_to_xml
36
+ raise_if_error
37
+ response_xml
38
+ end
39
+
40
+ private
41
+
42
+ def response_xml
43
+ @response_xml ||= REXML::Document.new(@response_body)
44
+ rescue REXML::ParseException => e
45
+ raise WinRMHTTPTransportError.new(
46
+ "Unable to parse WinRM response: #{e.message}", @status_code)
47
+ end
48
+
49
+ def raise_if_error
50
+ return if @status_code == 200
51
+ raise_if_auth_error
52
+ raise_if_wsman_fault
53
+ raise_if_wmi_error
54
+ raise_transport_error
55
+ end
56
+
57
+ def raise_if_auth_error
58
+ raise WinRMAuthorizationError if @status_code == 401
59
+ end
60
+
61
+ def raise_if_wsman_fault
62
+ soap_errors = REXML::XPath.match(
63
+ response_xml,
64
+ "//#{WinRM::WSMV::SOAP::NS_SOAP_ENV}:Body/#{WinRM::WSMV::SOAP::NS_SOAP_ENV}:Fault/*")
65
+ return if soap_errors.empty?
66
+ fault = REXML::XPath.first(
67
+ soap_errors,
68
+ "//#{WinRM::WSMV::SOAP::NS_WSMAN_FAULT}:WSManFault")
69
+ raise WinRMWSManFault.new(fault.to_s, fault.attributes['Code']) unless fault.nil?
70
+ end
71
+
72
+ def raise_if_wmi_error
73
+ soap_errors = REXML::XPath.match(
74
+ response_xml,
75
+ "//#{WinRM::WSMV::SOAP::NS_SOAP_ENV}:Body/#{WinRM::WSMV::SOAP::NS_SOAP_ENV}:Fault/*")
76
+ return if soap_errors.empty?
77
+
78
+ error = REXML::XPath.first(
79
+ soap_errors,
80
+ "//#{WinRM::WSMV::SOAP::NS_WSMAN_MSFT}:MSFT_WmiError")
81
+ return if error.nil?
82
+
83
+ error_code = REXML::XPath.first(
84
+ error,
85
+ "//#{WinRM::WSMV::SOAP::NS_WSMAN_MSFT}:error_Code").text
86
+ raise WinRMWMIError.new(error.to_s, error_code)
87
+ end
88
+
89
+ def raise_transport_error
90
+ raise WinRMHTTPTransportError.new(
91
+ "Bad HTTP response returned from server. Body(if present):#{@response_body}",
92
+ @status_code
93
+ )
94
+ end
95
+ end
96
+ end