knife-windows 1.1.0 → 1.1.1

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -5
  3. data/.travis.yml +20 -20
  4. data/CHANGELOG.md +87 -83
  5. data/DOC_CHANGES.md +20 -20
  6. data/Gemfile +12 -12
  7. data/LICENSE +201 -201
  8. data/README.md +396 -396
  9. data/RELEASE_NOTES.md +34 -34
  10. data/Rakefile +21 -21
  11. data/appveyor.yml +42 -42
  12. data/ci.gemfile +15 -15
  13. data/features/knife_help.feature +20 -20
  14. data/features/support/env.rb +5 -5
  15. data/knife-windows.gemspec +28 -28
  16. data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +247 -247
  17. data/lib/chef/knife/bootstrap_windows_base.rb +407 -401
  18. data/lib/chef/knife/bootstrap_windows_ssh.rb +110 -110
  19. data/lib/chef/knife/bootstrap_windows_winrm.rb +95 -102
  20. data/lib/chef/knife/core/windows_bootstrap_context.rb +362 -362
  21. data/lib/chef/knife/knife_windows_base.rb +33 -33
  22. data/lib/chef/knife/windows_cert_generate.rb +155 -155
  23. data/lib/chef/knife/windows_cert_install.rb +68 -68
  24. data/lib/chef/knife/windows_helper.rb +36 -36
  25. data/lib/chef/knife/windows_listener_create.rb +107 -107
  26. data/lib/chef/knife/winrm.rb +122 -212
  27. data/lib/chef/knife/winrm_base.rb +118 -118
  28. data/lib/chef/knife/winrm_knife_base.rb +309 -218
  29. data/lib/chef/knife/winrm_session.rb +82 -82
  30. data/lib/chef/knife/winrm_shared_options.rb +47 -47
  31. data/lib/chef/knife/wsman_endpoint.rb +44 -44
  32. data/lib/chef/knife/wsman_test.rb +95 -95
  33. data/lib/knife-windows/path_helper.rb +234 -234
  34. data/lib/knife-windows/version.rb +6 -6
  35. data/spec/assets/win_template_rendered_with_bootstrap_install_command.txt +217 -217
  36. data/spec/assets/win_template_rendered_with_bootstrap_install_command_on_12_5_client.txt +217 -217
  37. data/spec/assets/win_template_rendered_without_bootstrap_install_command.txt +329 -329
  38. data/spec/assets/win_template_rendered_without_bootstrap_install_command_on_12_5_client.txt +329 -329
  39. data/spec/assets/win_template_unrendered.txt +246 -246
  40. data/spec/functional/bootstrap_download_spec.rb +234 -233
  41. data/spec/spec_helper.rb +88 -88
  42. data/spec/unit/knife/bootstrap_options_spec.rb +148 -146
  43. data/spec/unit/knife/bootstrap_template_spec.rb +92 -92
  44. data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +259 -243
  45. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +151 -151
  46. data/spec/unit/knife/windows_cert_generate_spec.rb +90 -90
  47. data/spec/unit/knife/windows_cert_install_spec.rb +51 -51
  48. data/spec/unit/knife/windows_listener_create_spec.rb +76 -76
  49. data/spec/unit/knife/winrm_session_spec.rb +73 -73
  50. data/spec/unit/knife/winrm_spec.rb +551 -504
  51. data/spec/unit/knife/wsman_test_spec.rb +178 -175
  52. metadata +3 -23
@@ -1,83 +1,83 @@
1
- #
2
- # Author:: Steven Murawski <smurawski@chef.io>
3
- # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'chef/application'
20
- require 'winrm'
21
-
22
- class Chef
23
- class Knife
24
- class WinrmSession
25
- attr_reader :host, :endpoint, :port, :output, :error, :exit_code
26
-
27
- def initialize(options)
28
- Chef::Application.new.configure_proxy_environment_variables
29
- @host = options[:host]
30
- @port = options[:port]
31
- url = "#{options[:host]}:#{options[:port]}/wsman"
32
- scheme = options[:transport] == :ssl ? 'https' : 'http'
33
- @endpoint = "#{scheme}://#{url}"
34
-
35
- opts = Hash.new
36
- opts = {:user => options[:user], :pass => options[:password], :basic_auth_only => options[:basic_auth_only], :disable_sspi => options[:disable_sspi], :no_ssl_peer_verification => options[:no_ssl_peer_verification]}
37
- options[:transport] == :kerberos ? opts.merge!({:service => options[:service], :realm => options[:realm], :keytab => options[:keytab]}) : opts.merge!({:ca_trust_path => options[:ca_trust_path]})
38
-
39
- Chef::Log.debug("WinRM::WinRMWebService options: #{opts}")
40
- Chef::Log.debug("Endpoint: #{endpoint}")
41
- Chef::Log.debug("Transport: #{options[:transport]}")
42
-
43
- WinrmSession.load_windows_specific_gems if options[:transport] == :sspinegotiate
44
- @winrm_session = WinRM::WinRMWebService.new(@endpoint, options[:transport], opts)
45
- @winrm_session.set_timeout(options[:operation_timeout]) if options[:operation_timeout]
46
- end
47
-
48
- def relay_command(command)
49
- remote_id = @winrm_session.open_shell
50
- command_id = @winrm_session.run_command(remote_id, command)
51
- Chef::Log.debug("#{@host}[#{remote_id}] => :run_command[#{command}]")
52
- session_result = get_output(remote_id, command_id)
53
- @winrm_session.cleanup_command(remote_id, command_id)
54
- Chef::Log.debug("#{@host}[#{remote_id}] => :command_cleanup[#{command}]")
55
- @exit_code = session_result[:exitcode]
56
- @winrm_session.close_shell(remote_id)
57
- Chef::Log.debug("#{@host}[#{remote_id}] => :shell_close")
58
- end
59
-
60
- def get_output(remote_id, command_id)
61
- @winrm_session.get_command_output(remote_id, command_id) do |out,error|
62
- print_data(@host, out) if out
63
- print_data(@host, error, :red) if error
64
- end
65
- end
66
-
67
- def print_data(host, data, color = :cyan)
68
- if data =~ /\n/
69
- data.split(/\n/).each { |d| print_data(host, d, color) }
70
- elsif !data.nil?
71
- print Chef::Knife::Winrm.ui.color(host, color)
72
- puts " #{data}"
73
- end
74
- end
75
-
76
- def self.load_windows_specific_gems
77
- #checking for windows in case testing on linux
78
- require 'winrm-s'
79
- Chef::Log.debug("Applied 'winrm-s' monkey patch and trying WinRM communication with 'sspinegotiate'")
80
- end
81
- end
82
- end
1
+ #
2
+ # Author:: Steven Murawski <smurawski@chef.io>
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/application'
20
+ require 'winrm'
21
+
22
+ class Chef
23
+ class Knife
24
+ class WinrmSession
25
+ attr_reader :host, :endpoint, :port, :output, :error, :exit_code
26
+
27
+ def initialize(options)
28
+ Chef::Application.new.configure_proxy_environment_variables
29
+ @host = options[:host]
30
+ @port = options[:port]
31
+ url = "#{options[:host]}:#{options[:port]}/wsman"
32
+ scheme = options[:transport] == :ssl ? 'https' : 'http'
33
+ @endpoint = "#{scheme}://#{url}"
34
+
35
+ opts = Hash.new
36
+ opts = {:user => options[:user], :pass => options[:password], :basic_auth_only => options[:basic_auth_only], :disable_sspi => options[:disable_sspi], :no_ssl_peer_verification => options[:no_ssl_peer_verification]}
37
+ options[:transport] == :kerberos ? opts.merge!({:service => options[:service], :realm => options[:realm], :keytab => options[:keytab]}) : opts.merge!({:ca_trust_path => options[:ca_trust_path]})
38
+
39
+ Chef::Log.debug("WinRM::WinRMWebService options: #{opts}")
40
+ Chef::Log.debug("Endpoint: #{endpoint}")
41
+ Chef::Log.debug("Transport: #{options[:transport]}")
42
+
43
+ WinrmSession.load_windows_specific_gems if options[:transport] == :sspinegotiate
44
+ @winrm_session = WinRM::WinRMWebService.new(@endpoint, options[:transport], opts)
45
+ @winrm_session.set_timeout(options[:operation_timeout]) if options[:operation_timeout]
46
+ end
47
+
48
+ def relay_command(command)
49
+ remote_id = @winrm_session.open_shell
50
+ command_id = @winrm_session.run_command(remote_id, command)
51
+ Chef::Log.debug("#{@host}[#{remote_id}] => :run_command[#{command}]")
52
+ session_result = get_output(remote_id, command_id)
53
+ @winrm_session.cleanup_command(remote_id, command_id)
54
+ Chef::Log.debug("#{@host}[#{remote_id}] => :command_cleanup[#{command}]")
55
+ @exit_code = session_result[:exitcode]
56
+ @winrm_session.close_shell(remote_id)
57
+ Chef::Log.debug("#{@host}[#{remote_id}] => :shell_close")
58
+ end
59
+
60
+ def get_output(remote_id, command_id)
61
+ @winrm_session.get_command_output(remote_id, command_id) do |out,error|
62
+ print_data(@host, out) if out
63
+ print_data(@host, error, :red) if error
64
+ end
65
+ end
66
+
67
+ def print_data(host, data, color = :cyan)
68
+ if data =~ /\n/
69
+ data.split(/\n/).each { |d| print_data(host, d, color) }
70
+ elsif !data.nil?
71
+ print Chef::Knife::Winrm.ui.color(host, color)
72
+ puts " #{data}"
73
+ end
74
+ end
75
+
76
+ def self.load_windows_specific_gems
77
+ #checking for windows in case testing on linux
78
+ require 'winrm-s'
79
+ Chef::Log.debug("Applied 'winrm-s' monkey patch and trying WinRM communication with 'sspinegotiate'")
80
+ end
81
+ end
82
+ end
83
83
  end
@@ -1,47 +1,47 @@
1
- #
2
- # Author:: Steven Murawski (<smurawski@chef.io)
3
- # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'chef/knife'
20
- require 'chef/encrypted_data_bag_item'
21
- require 'kconv'
22
-
23
- class Chef
24
- class Knife
25
- module WinrmSharedOptions
26
-
27
- # Shared command line options for knife winrm and knife wsman test
28
- def self.included(includer)
29
- includer.class_eval do
30
- option :manual,
31
- :short => "-m",
32
- :long => "--manual-list",
33
- :boolean => true,
34
- :description => "QUERY is a space separated list of servers",
35
- :default => false
36
-
37
- option :attribute,
38
- :short => "-a ATTR",
39
- :long => "--attribute ATTR",
40
- :description => "The attribute to use for opening the connection - default is fqdn",
41
- :default => "fqdn"
42
- end
43
- end
44
-
45
- end
46
- end
47
- end
1
+ #
2
+ # Author:: Steven Murawski (<smurawski@chef.io)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife'
20
+ require 'chef/encrypted_data_bag_item'
21
+ require 'kconv'
22
+
23
+ class Chef
24
+ class Knife
25
+ module WinrmSharedOptions
26
+
27
+ # Shared command line options for knife winrm and knife wsman test
28
+ def self.included(includer)
29
+ includer.class_eval do
30
+ option :manual,
31
+ :short => "-m",
32
+ :long => "--manual-list",
33
+ :boolean => true,
34
+ :description => "QUERY is a space separated list of servers",
35
+ :default => false
36
+
37
+ option :attribute,
38
+ :short => "-a ATTR",
39
+ :long => "--attribute ATTR",
40
+ :description => "The attribute to use for opening the connection - default is fqdn",
41
+ :default => "fqdn"
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -1,44 +1,44 @@
1
- #
2
- # Author:: Steven Murawski (<smurawski@chef.io)
3
- # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- class Chef
20
- class Knife
21
- class WsmanEndpoint
22
- attr_accessor :host
23
- attr_accessor :wsman_port
24
- attr_accessor :wsman_url
25
- attr_accessor :product_version
26
- attr_accessor :protocol_version
27
- attr_accessor :product_vendor
28
- attr_accessor :response_status_code
29
- attr_accessor :error_message
30
-
31
- def initialize(name, port, url)
32
- @host = name
33
- @wsman_port = port
34
- @wsman_url = url
35
- end
36
-
37
- def to_hash
38
- hash = {}
39
- instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var) }
40
- hash
41
- end
42
- end
43
- end
44
- end
1
+ #
2
+ # Author:: Steven Murawski (<smurawski@chef.io)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ class Chef
20
+ class Knife
21
+ class WsmanEndpoint
22
+ attr_accessor :host
23
+ attr_accessor :wsman_port
24
+ attr_accessor :wsman_url
25
+ attr_accessor :product_version
26
+ attr_accessor :protocol_version
27
+ attr_accessor :product_vendor
28
+ attr_accessor :response_status_code
29
+ attr_accessor :error_message
30
+
31
+ def initialize(name, port, url)
32
+ @host = name
33
+ @wsman_port = port
34
+ @wsman_url = url
35
+ end
36
+
37
+ def to_hash
38
+ hash = {}
39
+ instance_variables.each {|var| hash[var.to_s.delete("@")] = instance_variable_get(var) }
40
+ hash
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,95 +1,95 @@
1
- #
2
- # Author:: Steven Murawski (<smurawski@chef.io>)
3
- # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
- # License:: Apache License, Version 2.0
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'httpclient'
20
- require 'chef/knife'
21
- require 'chef/knife/winrm_knife_base'
22
- require 'chef/knife/wsman_endpoint'
23
-
24
- class Chef
25
- class Knife
26
- class WsmanTest < Knife
27
-
28
- include Chef::Knife::WinrmCommandSharedFunctions
29
-
30
- deps do
31
- require 'chef/search/query'
32
- end
33
-
34
- banner "knife wsman test QUERY (options)"
35
-
36
- def run
37
- @config[:winrm_authentication_protocol] = 'basic'
38
- configure_session
39
- verify_wsman_accessiblity_for_nodes
40
- end
41
-
42
- def verify_wsman_accessiblity_for_nodes
43
- error_count = 0
44
- @winrm_sessions.each do |item|
45
- Chef::Log.debug("checking for WSMAN availability at #{item.endpoint}")
46
-
47
- xml = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>'
48
- header = {
49
- 'WSMANIDENTIFY' => 'unauthenticated',
50
- 'Content-Type' => 'application/soap+xml; charset=UTF-8'
51
- }
52
- output_object = Chef::Knife::WsmanEndpoint.new(item.host, item.port, item.endpoint)
53
- error_message = nil
54
- begin
55
- client = HTTPClient.new
56
- response = client.post(item.endpoint, xml, header)
57
- rescue Exception => e
58
- error_message = e.message
59
- else
60
- ui.msg "Connected successfully to #{item.host} at #{item.endpoint}."
61
- output_object.response_status_code = response.status_code
62
- end
63
-
64
- if response.nil? || output_object.response_status_code != 200
65
- error_message = "No valid WSMan endoint listening at #{item.endpoint}."
66
- else
67
- require 'nokogiri'
68
- doc = Nokogiri::XML response.body
69
- namespace = 'http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd'
70
- output_object.protocol_version = doc.xpath('//wsmid:ProtocolVersion', 'wsmid' => namespace).text
71
- output_object.product_version = doc.xpath('//wsmid:ProductVersion', 'wsmid' => namespace).text
72
- output_object.product_vendor = doc.xpath('//wsmid:ProductVendor', 'wsmid' => namespace).text
73
- if output_object.protocol_version.to_s.strip.length == 0
74
- error_message = "Endpoint #{item.endpoint} on #{item.host} does not appear to be a WSMAN endpoint."
75
- end
76
- end
77
-
78
- unless error_message.nil?
79
- ui.warn "Failed to connect to #{item.host} at #{item.endpoint}."
80
- output_object.error_message = error_message
81
- error_count += 1
82
- end
83
-
84
- if config[:verbosity] >= 1
85
- output(output_object)
86
- end
87
- end
88
- if error_count > 0
89
- ui.error "Failed to connect to #{error_count} nodes."
90
- exit 1
91
- end
92
- end
93
- end
94
- end
95
- end
1
+ #
2
+ # Author:: Steven Murawski (<smurawski@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'httpclient'
20
+ require 'chef/knife'
21
+ require 'chef/knife/winrm_knife_base'
22
+ require 'chef/knife/wsman_endpoint'
23
+
24
+ class Chef
25
+ class Knife
26
+ class WsmanTest < Knife
27
+
28
+ include Chef::Knife::WinrmCommandSharedFunctions
29
+
30
+ deps do
31
+ require 'chef/search/query'
32
+ end
33
+
34
+ banner "knife wsman test QUERY (options)"
35
+
36
+ def run
37
+ @config[:winrm_authentication_protocol] = 'basic'
38
+ configure_session
39
+ verify_wsman_accessiblity_for_nodes
40
+ end
41
+
42
+ def verify_wsman_accessiblity_for_nodes
43
+ error_count = 0
44
+ @winrm_sessions.each do |item|
45
+ Chef::Log.debug("checking for WSMAN availability at #{item.endpoint}")
46
+
47
+ xml = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd"><s:Header/><s:Body><wsmid:Identify/></s:Body></s:Envelope>'
48
+ header = {
49
+ 'WSMANIDENTIFY' => 'unauthenticated',
50
+ 'Content-Type' => 'application/soap+xml; charset=UTF-8'
51
+ }
52
+ output_object = Chef::Knife::WsmanEndpoint.new(item.host, item.port, item.endpoint)
53
+ error_message = nil
54
+ begin
55
+ client = HTTPClient.new
56
+ response = client.post(item.endpoint, xml, header)
57
+ rescue Exception => e
58
+ error_message = e.message
59
+ else
60
+ ui.msg "Connected successfully to #{item.host} at #{item.endpoint}."
61
+ output_object.response_status_code = response.status_code
62
+ end
63
+
64
+ if response.nil? || output_object.response_status_code != 200
65
+ error_message = "No valid WSMan endoint listening at #{item.endpoint}."
66
+ else
67
+ require 'nokogiri'
68
+ doc = Nokogiri::XML response.body
69
+ namespace = 'http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd'
70
+ output_object.protocol_version = doc.xpath('//wsmid:ProtocolVersion', 'wsmid' => namespace).text
71
+ output_object.product_version = doc.xpath('//wsmid:ProductVersion', 'wsmid' => namespace).text
72
+ output_object.product_vendor = doc.xpath('//wsmid:ProductVendor', 'wsmid' => namespace).text
73
+ if output_object.protocol_version.to_s.strip.length == 0
74
+ error_message = "Endpoint #{item.endpoint} on #{item.host} does not appear to be a WSMAN endpoint."
75
+ end
76
+ end
77
+
78
+ unless error_message.nil?
79
+ ui.warn "Failed to connect to #{item.host} at #{item.endpoint}."
80
+ output_object.error_message = error_message
81
+ error_count += 1
82
+ end
83
+
84
+ if config[:verbosity] >= 1
85
+ output(output_object)
86
+ end
87
+ end
88
+ if error_count > 0
89
+ ui.error "Failed to connect to #{error_count} nodes."
90
+ exit 1
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end