ridley 0.12.4 → 1.0.0.rc1

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 (39) hide show
  1. data/Gemfile +1 -1
  2. data/lib/ridley.rb +3 -3
  3. data/lib/ridley/bootstrap_context.rb +100 -0
  4. data/lib/ridley/bootstrap_context/unix.rb +74 -0
  5. data/lib/ridley/bootstrap_context/windows.rb +120 -0
  6. data/lib/ridley/chef_objects/node_object.rb +8 -5
  7. data/lib/ridley/host_commander.rb +207 -0
  8. data/lib/ridley/host_connector.rb +49 -87
  9. data/lib/ridley/host_connector/ssh.rb +153 -39
  10. data/lib/ridley/host_connector/winrm.rb +164 -39
  11. data/lib/ridley/resources/node_resource.rb +52 -56
  12. data/lib/ridley/version.rb +1 -1
  13. data/ridley.gemspec +0 -2
  14. data/spec/spec_helper.rb +4 -4
  15. data/spec/support/chef_server.rb +9 -3
  16. data/spec/unit/ridley/{bootstrap_bindings/unix_template_binding_spec.rb → bootstrap_context/unix_spec.rb} +2 -2
  17. data/spec/unit/ridley/{bootstrap_bindings/windows_template_binding_spec.rb → bootstrap_context/windows_spec.rb} +2 -2
  18. data/spec/unit/ridley/{mixin/bootstrap_binding_spec.rb → bootstrap_context_spec.rb} +2 -6
  19. data/spec/unit/ridley/host_commander_spec.rb +208 -0
  20. data/spec/unit/ridley/host_connector/ssh_spec.rb +37 -31
  21. data/spec/unit/ridley/host_connector/winrm_spec.rb +124 -31
  22. data/spec/unit/ridley/host_connector_spec.rb +23 -147
  23. data/spec/unit/ridley/resources/node_resource_spec.rb +55 -115
  24. metadata +17 -66
  25. data/lib/ridley/bootstrap_bindings.rb +0 -3
  26. data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +0 -108
  27. data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +0 -163
  28. data/lib/ridley/bootstrapper.rb +0 -89
  29. data/lib/ridley/bootstrapper/context.rb +0 -81
  30. data/lib/ridley/host_connector/response_set.rb +0 -98
  31. data/lib/ridley/host_connector/ssh/worker.rb +0 -135
  32. data/lib/ridley/host_connector/winrm/worker.rb +0 -159
  33. data/lib/ridley/log.rb +0 -10
  34. data/lib/ridley/mixin/bootstrap_binding.rb +0 -77
  35. data/spec/unit/ridley/bootstrapper/context_spec.rb +0 -45
  36. data/spec/unit/ridley/bootstrapper_spec.rb +0 -96
  37. data/spec/unit/ridley/host_connector/response_set_spec.rb +0 -112
  38. data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +0 -57
  39. data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +0 -139
@@ -1,111 +1,73 @@
1
- require 'socket'
2
- require 'timeout'
3
-
4
1
  module Ridley
5
2
  # @author Kyle Allan <kallan@riotgames.com>
6
3
  module HostConnector
7
- require_relative 'host_connector/response'
8
- require_relative 'host_connector/response_set'
9
- require_relative 'host_connector/ssh'
10
- require_relative 'host_connector/winrm'
11
-
12
- DEFAULT_SSH_PORT = 22.freeze
13
- DEFAULT_WINRM_PORT = 5985.freeze
4
+ class Base
5
+ include Celluloid
6
+ include Ridley::Logging
14
7
 
15
- class << self
16
- # Create a new connection worker for the given host. An SSH or WinRM connection will be returned
17
- # depending on which ports are open on the target host.
8
+ # Execute a shell command on a node
18
9
  #
19
10
  # @param [String] host
20
- # host to create a connector for
11
+ # the host to perform the action on
12
+ # @param [String] command
13
+ # @param [Hash] options
21
14
  #
22
- # @option options [Hash] ssh
23
- # * :user (String) a shell user that will login to each node and perform the bootstrap command on
24
- # * :password (String) the password for the shell user that will perform the bootstrap
25
- # * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
26
- # * :timeout (Float) [5.0] timeout value for SSH bootstrap
27
- # @option options [Hash] :winrm
28
- # * :user (String) a user that will login to each node and perform the bootstrap command on
29
- # * :password (String) the password for the user that will perform the bootstrap
30
- # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on
31
- #
32
- # @return [SSH::Worker, WinRM::Worker]
33
- def new(host, options = {})
34
- HostConnector.best_connector_for(host, options) do |host_connector|
35
- host_connector::Worker.new(host, options)
36
- end
15
+ # @return [HostConnector::Response]
16
+ def run(host, command, options = {})
17
+ raise RuntimeError, "abstract function: must be implemented on includer"
37
18
  end
38
19
 
39
- # Finds and returns the best HostConnector for a given host
20
+ # Bootstrap a node
40
21
  #
41
- # @param host [String]
42
- # the host to attempt to connect to
43
- # @option options [Hash] :ssh
44
- # * :port (Fixnum) the ssh port to connect on the node the bootstrap will be performed on (22)
45
- # * :timeout (Float) [5.0] timeout value for testing SSH connection
46
- # @option options [Hash] :winrm
47
- # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
48
- # @param block [Proc]
49
- # an optional block that is yielded the best HostConnector
22
+ # @param [String] host
23
+ # the host to perform the action on
24
+ # @param [Hash] options
50
25
  #
51
- # @return [Ridley::HostConnector] a class under Ridley::HostConnector
52
- def best_connector_for(host, options = {}, &block)
53
- ssh_port, winrm_port = parse_port_options(options)
54
- timeout = options[:ssh] && options[:ssh][:timeout]
55
-
56
- if connector_port_open?(host, winrm_port)
57
- host_connector = Ridley::HostConnector::WinRM
58
- elsif connector_port_open?(host, ssh_port, timeout)
59
- host_connector = Ridley::HostConnector::SSH
60
- else
61
- raise Ridley::Errors::HostConnectionError, "No available connection method available on #{host}."
62
- end
63
-
64
- if block_given?
65
- yield host_connector
66
- else
67
- host_connector
68
- end
26
+ # @return [HostConnector::Response]
27
+ def bootstrap(host, options = {})
28
+ raise RuntimeError, "abstract function: must be implemented on includer"
69
29
  end
70
30
 
71
- # Checks to see if the given port is open for TCP connections
72
- # on the given host.
31
+ # Perform a chef client run on a node
73
32
  #
74
- # @param host [String]
75
- # the host to attempt to connect to
76
- # @param port [Fixnum]
77
- # the port to attempt to connect on
78
- # @param timeout [Float]
79
- # the number of seconds to wait (default: 3)
33
+ # @param [String] host
34
+ # the host to perform the action on
35
+ # @param [Hash] options
80
36
  #
81
- # @return [Boolean]
82
- def connector_port_open?(host, port, timeout = nil)
83
- timeout ||= 3
84
-
85
- Timeout::timeout(timeout) do
86
- socket = TCPSocket.new(host, port)
87
- socket.close
88
- end
37
+ # @return [HostConnector::Response]
38
+ def chef_client(host, options = {})
39
+ raise RuntimeError, "abstract function: must be implemented on includer"
40
+ end
89
41
 
90
- true
91
- rescue Timeout::Error, SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH
92
- false
42
+ # Write your encrypted data bag secret on a node
43
+ #
44
+ # @param [String] host
45
+ # the host to perform the action on
46
+ # @param [String] secret
47
+ # your organization's encrypted data bag secret
48
+ # @param [Hash] options
49
+ #
50
+ # @return [HostConnector::Response]
51
+ def put_secret(host, secret, options = {})
52
+ raise RuntimeError, "abstract function: must be implemented on includer"
93
53
  end
94
54
 
95
- # Parses the options Hash and returns an array of
96
- # [SSH_PORT, WINRM_PORT] used to attempt to connect to.
55
+ # Execute line(s) of Ruby code on a node using Chef's embedded Ruby
97
56
  #
98
- # @option options [Hash] :ssh
99
- # * :port (Fixnum) the ssh port to connect on the node the bootstrap will be performed on (22)
100
- # @option options [Hash] :winrm
101
- # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
57
+ # @param [String] host
58
+ # the host to perform the action on
59
+ # @param [Array<String>] command_lines
60
+ # An Array of lines of the command to be executed
61
+ # @param [Hash] options
102
62
  #
103
- # @return [Array]
104
- def parse_port_options(options)
105
- ssh_port = options[:ssh][:port] if options[:ssh]
106
- winrm_port = options[:winrm][:port] if options[:winrm]
107
- [ssh_port || DEFAULT_SSH_PORT, winrm_port || DEFAULT_WINRM_PORT]
63
+ # @return [HostConnector::Response]
64
+ def ruby_script(host, command_lines, options = {})
65
+ raise RuntimeError, "abstract function: must be implemented on includer"
108
66
  end
109
67
  end
68
+
69
+ require_relative 'host_connector/response'
70
+ require_relative 'host_connector/ssh'
71
+ require_relative 'host_connector/winrm'
110
72
  end
111
73
  end
@@ -3,56 +3,170 @@ require 'net/ssh'
3
3
  module Ridley
4
4
  module HostConnector
5
5
  # @author Jamie Winsor <reset@riotgames.com>
6
- class SSH
7
- require_relative 'ssh/worker'
8
-
9
- class << self
10
- # @param [Ridley::NodeObject, Array<Ridley::NodeObject>] nodes
11
- # @param [Hash] options
12
- def start(nodes, options = {}, &block)
13
- runner = new(nodes, options)
14
- result = yield runner
15
- runner.terminate
16
-
17
- result
18
- ensure
19
- runner.terminate if runner && runner.alive?
6
+ class SSH < HostConnector::Base
7
+ DEFAULT_PORT = 22
8
+ EMBEDDED_RUBY_PATH = '/opt/chef/embedded/bin/ruby'.freeze
9
+
10
+ # Execute a shell command on a node
11
+ #
12
+ # @param [String] host
13
+ # the host to perform the action on
14
+ # @param [String] command
15
+ #
16
+ # @option options [Hash] :ssh
17
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
18
+ # * :password (String) the password for the shell user that will perform the bootstrap
19
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
20
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
21
+ # * :sudo (Boolean) run as sudo
22
+ #
23
+ # @return [HostConnector::Response]
24
+ def run(host, command, options = {})
25
+ options = options.reverse_merge(ssh: Hash.new)
26
+ options[:ssh].reverse_merge!(port: DEFAULT_PORT, paranoid: false, sudo: false)
27
+
28
+ command = "sudo #{command}" if options[:sudo]
29
+
30
+ Ridley::HostConnector::Response.new(host).tap do |response|
31
+ begin
32
+ log.info "Running SSH command: '#{command}' on: '#{host}' as: '#{options[:ssh][:user]}'"
33
+
34
+ Net::SSH.start(host, options[:ssh][:user], options[:ssh].slice(*Net::SSH::VALID_OPTIONS)) do |ssh|
35
+ ssh.open_channel do |channel|
36
+ if options[:sudo]
37
+ channel.request_pty do |channel, success|
38
+ unless success
39
+ raise "Could not aquire pty: A pty is required for running sudo commands."
40
+ end
41
+
42
+ channel_exec(channel, command, host, response)
43
+ end
44
+ else
45
+ channel_exec(channel, command, host, response)
46
+ end
47
+ end
48
+ ssh.loop
49
+ end
50
+ rescue Net::SSH::Exception => ex
51
+ response.exit_code = -1
52
+ response.stderr = ex.message
53
+ return response
54
+ end
55
+
56
+ case response.exit_code
57
+ when 0
58
+ log.info "Successfully ran SSH command on: '#{host}' as: '#{options[:ssh][:user]}'"
59
+ else
60
+ log.info "Successfully ran SSH command on: '#{host}' as: '#{options[:ssh][:user]}' but it failed"
61
+ end
20
62
  end
21
63
  end
22
64
 
23
- include Celluloid
24
- include Celluloid::Logger
65
+ # Bootstrap a node
66
+ #
67
+ # @param [String] host
68
+ # the host to perform the action on
69
+ #
70
+ # @option options [Hash] :ssh
71
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
72
+ # * :password (String) the password for the shell user that will perform the bootstrap
73
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
74
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
75
+ # * :sudo (Boolean) run as sudo
76
+ #
77
+ # @return [HostConnector::Response]
78
+ def bootstrap(host, options = {})
79
+ options = options.reverse_merge(ssh: Hash.new)
80
+ options[:ssh].reverse_merge!(sudo: true, timeout: 5.0)
81
+ context = BootstrapContext::Unix.new(options)
25
82
 
26
- attr_reader :nodes
27
- attr_reader :options
83
+ log.info "Bootstrapping host: #{host}"
84
+ run(host, context.boot_command, options)
85
+ end
28
86
 
29
- # @param [Ridley::NodeObject, Array<Ridley::NodeObject>] nodes
30
- # @param [Hash] options
31
- # @see Net::SSH
32
- def initialize(nodes, options = {})
33
- @nodes = Array(nodes)
34
- @options = options
87
+ # Perform a chef client run on a node
88
+ #
89
+ # @param [String] host
90
+ # the host to perform the action on
91
+ #
92
+ # @option options [Hash] :ssh
93
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
94
+ # * :password (String) the password for the shell user that will perform the bootstrap
95
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
96
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
97
+ # * :sudo (Boolean) run as sudo
98
+ #
99
+ # @return [HostConnector::Response]
100
+ def chef_client(host, options = {})
101
+ run(host, "chef-client", options)
35
102
  end
36
103
 
37
- # @param [String] command
104
+ # Write your encrypted data bag secret on a node
38
105
  #
39
- # @return [Array]
40
- def run(command)
41
- workers = Array.new
42
- futures = self.nodes.collect do |node|
43
- workers << worker = Worker.new(node.public_hostname, self.options.freeze)
44
- worker.future.run(command)
45
- end
106
+ # @param [String] host
107
+ # the host to perform the action on
108
+ # @param [String] secret
109
+ # your organization's encrypted data bag secret
110
+ #
111
+ # @option options [Hash] :ssh
112
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
113
+ # * :password (String) the password for the shell user that will perform the bootstrap
114
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
115
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
116
+ # * :sudo (Boolean) run as sudo
117
+ #
118
+ # @return [HostConnector::Response]
119
+ def put_secret(host, secret, options = {})
120
+ cmd = "echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret"
121
+ run(host, cmd, options)
122
+ end
46
123
 
47
- ResponseSet.new.tap do |response_set|
48
- futures.each do |future|
49
- status, response = future.value
50
- response_set.add_response(response)
124
+ # Execute line(s) of Ruby code on a node using Chef's embedded Ruby
125
+ #
126
+ # @param [String] host
127
+ # the host to perform the action on
128
+ # @param [Array<String>] command_lines
129
+ # An Array of lines of the command to be executed
130
+ #
131
+ # @option options [Hash] :ssh
132
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on
133
+ # * :password (String) the password for the shell user that will perform the bootstrap
134
+ # * :keys (Array, String) an array of key(s) to authenticate the ssh user with instead of a password
135
+ # * :timeout (Float) timeout value for SSH bootstrap (5.0)
136
+ # * :sudo (Boolean) run as sudo
137
+ #
138
+ # @return [HostConnector::Response]
139
+ def ruby_script(host, command_lines, options = {})
140
+ run(host, "#{EMBEDDED_RUBY_PATH} -e \"#{command_lines.join(';')}\"", options)
141
+ end
142
+
143
+ private
144
+
145
+ def channel_exec(channel, command, host, response)
146
+ channel.exec(command) do |ch, success|
147
+ unless success
148
+ raise "Channel execution failed while executing command #{command}"
149
+ end
150
+
151
+ channel.on_data do |ch, data|
152
+ response.stdout += data
153
+ log.info "[#{host}](SSH) #{data}" if data.present? and data != "\r\n"
154
+ end
155
+
156
+ channel.on_extended_data do |ch, type, data|
157
+ response.stderr += data
158
+ log.info "[#{host}](SSH) #{data}" if data.present? and data != "\r\n"
159
+ end
160
+
161
+ channel.on_request("exit-status") do |ch, data|
162
+ response.exit_code = data.read_long
163
+ end
164
+
165
+ channel.on_request("exit-signal") do |ch, data|
166
+ response.exit_signal = data.read_string
167
+ end
51
168
  end
52
169
  end
53
- ensure
54
- workers.map(&:terminate)
55
- end
56
170
  end
57
171
  end
58
172
  end
@@ -1,56 +1,181 @@
1
+ require 'active_support/core_ext/kernel/reporting'
2
+ # Silencing warnings because not all versions of GSSAPI support all of the GSSAPI methods
3
+ # the gssapi gem attempts to attach to and these warnings are dumped to STDERR.
4
+ silence_warnings do
5
+ require 'winrm'
6
+ end
7
+
1
8
  module Ridley
2
9
  module HostConnector
3
10
  # @author Kyle Allan <kallan@riotgames.com>
4
- class WinRM
11
+ class WinRM < HostConnector::Base
5
12
  require_relative 'winrm/command_uploader'
6
- require_relative 'winrm/worker'
7
-
8
- class << self
9
- # @param [Ridley::NodeResource, Array<Ridley::NodeResource>] nodes
10
- # @param [Hash] options
11
- def start(nodes, options = {}, &block)
12
- runner = new(nodes, options)
13
- result = yield runner
14
- runner.terminate
15
-
16
- result
17
- ensure
18
- runner.terminate if runner && runner.alive?
13
+
14
+ DEFAULT_PORT = 5985
15
+ EMBEDDED_RUBY_PATH = 'C:\opscode\chef\embedded\bin\ruby'.freeze
16
+
17
+ # Execute a shell command on a node
18
+ #
19
+ # @param [String] host
20
+ # the host to perform the action on
21
+ # @param [String] command
22
+ #
23
+ # @option options [Hash] :winrm
24
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
25
+ # * :password (String) the password for the user that will perform the bootstrap (required)
26
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
27
+ #
28
+ # @return [HostConnector::Response]
29
+ def run(host, command, options = {})
30
+ options = options.reverse_merge(winrm: Hash.new)
31
+ options[:winrm].reverse_merge!(port: DEFAULT_PORT)
32
+
33
+ command_uploaders = Array.new
34
+ user = options[:winrm][:user]
35
+ password = options[:winrm][:password]
36
+ port = options[:winrm][:port]
37
+ connection = winrm(host, port, options[:winrm].slice(:user, :password))
38
+
39
+ HostConnector::Response.new(host).tap do |response|
40
+ command_uploaders << command_uploader = CommandUploader.new(connection)
41
+ command = get_command(command, command_uploader)
42
+
43
+ begin
44
+ log.info "Running WinRM Command: '#{command}' on: '#{host}' as: '#{user}'"
45
+
46
+ output = connection.run_cmd(command) do |stdout, stderr|
47
+ if stdout
48
+ response.stdout += stdout
49
+ log.info "[#{host}](WinRM) #{stdout}"
50
+ end
51
+
52
+ if stderr
53
+ response.stderr += stderr unless stderr.nil?
54
+ log.info "[#{host}](WinRM) #{stdout}"
55
+ end
56
+ end
57
+
58
+ response.exit_code = output[:exitcode]
59
+ rescue ::WinRM::WinRMHTTPTransportError => ex
60
+ response.exit_code = -1
61
+ response.stderr = ex.message
62
+ return response
63
+ end
64
+
65
+ case response.exit_code
66
+ when 0
67
+ log.info "Successfully ran WinRM command on: '#{host}' as: '#{user}'"
68
+ else
69
+ log.info "Successfully ran WinRM command on: '#{host}' as: '#{user}', but it failed"
70
+ end
71
+ end
72
+ ensure
73
+ command_uploaders.map(&:cleanup)
74
+ end
75
+
76
+ # Returns the command if it does not break the WinRM command length
77
+ # limit. Otherwise, we return an execution of the command as a batch file.
78
+ #
79
+ # @param command [String]
80
+ #
81
+ # @return [String]
82
+ def get_command(command, command_uploader)
83
+ if command.length < CommandUploader::CHUNK_LIMIT
84
+ command
85
+ else
86
+ log.debug "Detected a command that was longer than #{CommandUploader::CHUNK_LIMIT} characters. " +
87
+ "Uploading command as a file to the host."
88
+ command_uploader.upload(command)
89
+ command_uploader.command
19
90
  end
20
91
  end
21
92
 
22
- include Celluloid
23
- include Celluloid::Logger
93
+ # Bootstrap a node
94
+ #
95
+ # @param [String] host
96
+ # the host to perform the action on
97
+ #
98
+ # @option options [Hash] :winrm
99
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
100
+ # * :password (String) the password for the user that will perform the bootstrap (required)
101
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
102
+ #
103
+ # @return [HostConnector::Response]
104
+ def bootstrap(host, options = {})
105
+ context = BootstrapContext::Windows.new(options)
24
106
 
25
- attr_reader :nodes
26
- attr_reader :options
107
+ log.info "Bootstrapping host: #{host}"
108
+ run(host, context.boot_command, options)
109
+ end
27
110
 
28
- # @param [Ridley::NodeResource, Array<Ridley::NodeResource>] nodes
29
- # @param [Hash] options
30
- def initialize(nodes, options = {})
31
- @nodes = Array(nodes)
32
- @options = options
111
+ # Perform a chef client run on a node
112
+ #
113
+ # @param [String] host
114
+ # the host to perform the action on
115
+ #
116
+ # @option options [Hash] :winrm
117
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
118
+ # * :password (String) the password for the user that will perform the bootstrap (required)
119
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
120
+ #
121
+ # @return [HostConnector::Response]
122
+ def chef_client(host, options = {})
123
+ run(host, "chef-client", options)
33
124
  end
34
125
 
35
- # @param [String] command
126
+ # Write your encrypted data bag secret on a node
36
127
  #
37
- # @return [Array]
38
- def run(command)
39
- workers = Array.new
40
- futures = self.nodes.collect do |node|
41
- workers << worker = Worker.new(node.public_hostname, self.options.freeze)
42
- worker.future.run(command)
43
- end
128
+ # @param [String] host
129
+ # the host to perform the action on
130
+ # @param [String] secret
131
+ # your organization's encrypted data bag secret
132
+ #
133
+ # @option options [Hash] :winrm
134
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
135
+ # * :password (String) the password for the user that will perform the bootstrap (required)
136
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
137
+ #
138
+ # @return [HostConnector::Response]
139
+ def put_secret(host, secret, options = {})
140
+ command = "echo #{secret} > C:\\chef\\encrypted_data_bag_secret"
141
+ run(host, command, options)
142
+ end
44
143
 
45
- Ridley::HostConnector::ResponseSet.new.tap do |response_set|
46
- futures.each do |future|
47
- status, response = future.value
48
- response_set.add_response(response)
49
- end
50
- end
51
- ensure
52
- workers.map(&:terminate)
144
+ # Execute line(s) of Ruby code on a node using Chef's embedded Ruby
145
+ #
146
+ # @param [String] host
147
+ # the host to perform the action on
148
+ # @param [Array<String>] command_lines
149
+ # An Array of lines of the command to be executed
150
+ #
151
+ # @option options [Hash] :winrm
152
+ # * :user (String) a user that will login to each node and perform the bootstrap command on
153
+ # * :password (String) the password for the user that will perform the bootstrap (required)
154
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
155
+ #
156
+ # @return [HostConnector::Response]
157
+ def ruby_script(host, command_lines, options = {})
158
+ command = "#{EMBEDDED_RUBY_PATH} -e \"#{command_lines.join(';')}\""
159
+ run(host, command, options)
53
160
  end
161
+
162
+ private
163
+
164
+ # @param [String] host
165
+ # @param [Integer] port
166
+ #
167
+ # @option options [String] :user
168
+ # @option options [String] :password
169
+ #
170
+ # @return [WinRM::WinRMWebService]
171
+ def winrm(host, port, options = {})
172
+ winrm_opts = { disable_sspi: true, basic_auth_only: true }
173
+ winrm_opts[:user] = options[:user]
174
+ winrm_opts[:pass] = options[:password]
175
+ client = ::WinRM::WinRMWebService.new("http://#{host}:#{port}/wsman", :plaintext, winrm_opts)
176
+ client.set_timeout(6000)
177
+ client
178
+ end
54
179
  end
55
180
  end
56
181
  end