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
@@ -14,6 +14,8 @@ module Ridley
14
14
  attr_reader :winrm
15
15
  attr_reader :chef_version
16
16
 
17
+ finalizer :finalize_callback
18
+
17
19
  # @param [Celluloid::Registry] connection_registry
18
20
  #
19
21
  # @option options [String] :server_url
@@ -43,48 +45,45 @@ module Ridley
43
45
  @ssh = options[:ssh]
44
46
  @winrm = options[:winrm]
45
47
  @chef_version = options[:chef_version]
48
+ @host_commander = HostCommander.new_link
46
49
  end
47
50
 
48
- # @overload bootstrap(nodes, options = {})
49
- # @param [Array<String>, String] nodes
51
+ # @param [String] host
50
52
  #
51
- # @option options [Hash] ssh
52
- # * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
53
- # * :password (String) the password for the shell user that will perform the bootstrap
54
- # * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
55
- # * :timeout (Float) [5.0] timeout value for SSH bootstrap
56
- # @option options [Hash] :winrm
57
- # * :user (String) a user that will login to each node and perform the bootstrap command on (required)
58
- # * :password (String) the password for the user that will perform the bootstrap
59
- # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
60
- # @option options [String] :validator_client
61
- # @option options [String] :validator_path
62
- # filepath to the validator used to bootstrap the node (required)
63
- # @option options [String] :bootstrap_proxy
64
- # URL to a proxy server to bootstrap through (default: nil)
65
- # @option options [String] :encrypted_data_bag_secret_path
66
- # filepath on your host machine to your organizations encrypted data bag secret (default: nil)
67
- # @option options [Hash] :hints
68
- # a hash of Ohai hints to place on the bootstrapped node (default: Hash.new)
69
- # @option options [Hash] :attributes
70
- # a hash of attributes to use in the first Chef run (default: Hash.new)
71
- # @option options [Array] :run_list
72
- # an initial run list to bootstrap with (default: Array.new)
73
- # @option options [String] :chef_version
74
- # version of Chef to install on the node (default: nil)
75
- # @option options [String] :environment
76
- # environment to join the node to (default: '_default')
77
- # @option options [Boolean] :sudo
78
- # bootstrap with sudo (default: true)
79
- # @option options [String] :template
80
- # bootstrap template to use (default: omnibus)
53
+ # @option options [Hash] ssh
54
+ # * :user (String) a shell user that will login to each node and perform the bootstrap command on (required)
55
+ # * :password (String) the password for the shell user that will perform the bootstrap
56
+ # * :keys (Array, String) an array of keys (or a single key) to authenticate the ssh user with instead of a password
57
+ # * :timeout (Float) [5.0] timeout value for SSH bootstrap
58
+ # @option options [Hash] :winrm
59
+ # * :user (String) a user that will login to each node and perform the bootstrap command on (required)
60
+ # * :password (String) the password for the user that will perform the bootstrap
61
+ # * :port (Fixnum) the winrm port to connect on the node the bootstrap will be performed on (5985)
62
+ # @option options [String] :validator_client
63
+ # @option options [String] :validator_path
64
+ # filepath to the validator used to bootstrap the node (required)
65
+ # @option options [String] :bootstrap_proxy
66
+ # URL to a proxy server to bootstrap through (default: nil)
67
+ # @option options [String] :encrypted_data_bag_secret_path
68
+ # filepath on your host machine to your organizations encrypted data bag secret (default: nil)
69
+ # @option options [Hash] :hints
70
+ # a hash of Ohai hints to place on the bootstrapped node (default: Hash.new)
71
+ # @option options [Hash] :attributes
72
+ # a hash of attributes to use in the first Chef run (default: Hash.new)
73
+ # @option options [Array] :run_list
74
+ # an initial run list to bootstrap with (default: Array.new)
75
+ # @option options [String] :chef_version
76
+ # version of Chef to install on the node (default: nil)
77
+ # @option options [String] :environment
78
+ # environment to join the node to (default: '_default')
79
+ # @option options [Boolean] :sudo
80
+ # bootstrap with sudo (default: true)
81
+ # @option options [String] :template
82
+ # bootstrap template to use (default: omnibus)
81
83
  #
82
- # @return [SSH::ResponseSet]
83
- def bootstrap(*args)
84
- args = args.dup
85
- opts = args.extract_options!
86
-
87
- options = opts.reverse_merge(
84
+ # @return [HostConnector::Response]
85
+ def bootstrap(host, options = {})
86
+ options = options.reverse_merge(
88
87
  server_url: server_url,
89
88
  validator_path: validator_path,
90
89
  validator_client: validator_client,
@@ -94,7 +93,7 @@ module Ridley
94
93
  chef_version: chef_version
95
94
  )
96
95
 
97
- Bootstrapper.new(args, options).run
96
+ host_commander.bootstrap(host, options)
98
97
  end
99
98
 
100
99
  # Executes a Chef run using the best worker available for the given
@@ -104,10 +103,7 @@ module Ridley
104
103
  #
105
104
  # @return [HostConnector::Response]
106
105
  def chef_run(host)
107
- worker = HostConnector.new(host, ssh: ssh, winrm: winrm)
108
- worker.chef_client
109
- ensure
110
- worker.terminate if worker && worker.alive?
106
+ host_commander.chef_client(host, ssh: ssh, winrm: winrm)
111
107
  end
112
108
 
113
109
  # Puts a secret on the host using the best worker available for
@@ -117,10 +113,7 @@ module Ridley
117
113
  #
118
114
  # @return [HostConnector::Response]
119
115
  def put_secret(host)
120
- worker = HostConnector.new(host, ssh: ssh, winrm: winrm)
121
- worker.put_secret(encrypted_data_bag_secret)
122
- ensure
123
- worker.terminate if worker && worker.alive?
116
+ host_commander.put_secret(host, encrypted_data_bag_secret, ssh: ssh, winrm: winrm)
124
117
  end
125
118
 
126
119
  # Executes an arbitrary ruby script using the best worker available
@@ -131,10 +124,7 @@ module Ridley
131
124
  #
132
125
  # @return [HostConnector::Response]
133
126
  def ruby_script(host, command_lines)
134
- worker = HostConnector.new(host, ssh: ssh, winrm: winrm)
135
- worker.ruby_script(command_lines)
136
- ensure
137
- worker.terminate if worker && worker.alive?
127
+ host_commander.ruby_script(host, command_lines, ssh: ssh, winrm: winrm)
138
128
  end
139
129
 
140
130
  # Executes the given command on a node using the best worker
@@ -145,10 +135,7 @@ module Ridley
145
135
  #
146
136
  # @return [Array<Symbol, HostConnector::Response>]
147
137
  def execute_command(host, command)
148
- worker = HostConnector.new(host, ssh: ssh, winrm: winrm)
149
- worker.run(command)
150
- ensure
151
- worker.terminate if worker && worker.alive?
138
+ host_commander.run(host, command, ssh: ssh, winrm: winrm)
152
139
  end
153
140
 
154
141
  # Merges the given data with the the data of the target node on the remote
@@ -164,7 +151,7 @@ module Ridley
164
151
  # @raise [Errors::ResourceNotFound]
165
152
  # if the target node is not found
166
153
  #
167
- # @return [Ridley::NodeResource]
154
+ # @return [Ridley::NodeObject]
168
155
  def merge_data(target, options = {})
169
156
  unless node = find(target)
170
157
  abort Errors::ResourceNotFound.new
@@ -172,5 +159,14 @@ module Ridley
172
159
 
173
160
  update(node.merge_data(options))
174
161
  end
162
+
163
+ private
164
+
165
+ # @return [Ridley::HostCommander]
166
+ attr_reader :host_commander
167
+
168
+ def finalize_callback
169
+ @host_commander.terminate if @host_commander && @host_commander.alive?
170
+ end
175
171
  end
176
172
  end
@@ -1,3 +1,3 @@
1
1
  module Ridley
2
- VERSION = "0.12.4"
2
+ VERSION = "1.0.0.rc1"
3
3
  end
data/ridley.gemspec CHANGED
@@ -23,9 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency 'erubis'
24
24
  s.add_runtime_dependency 'faraday', '>= 0.8.4'
25
25
  s.add_runtime_dependency 'hashie', '>= 2.0.2'
26
- s.add_runtime_dependency 'mixlib-log', '>= 1.3.0'
27
26
  s.add_runtime_dependency 'mixlib-shellout', '>= 1.1.0'
28
- s.add_runtime_dependency 'mixlib-config', '>= 1.1.0'
29
27
  s.add_runtime_dependency 'mixlib-authentication', '>= 1.3.0'
30
28
  s.add_runtime_dependency 'net-http-persistent', '>= 2.8'
31
29
  s.add_runtime_dependency 'net-ssh'
data/spec/spec_helper.rb CHANGED
@@ -19,13 +19,13 @@ def setup_rspec
19
19
  config.filter_run focus: true
20
20
  config.run_all_when_everything_filtered = true
21
21
 
22
- config.before(:suite) { Ridley::RSpec::ChefServer.start }
23
-
24
- config.before(:all) do
25
- Ridley.logger = Celluloid.logger = nil
22
+ config.before(:suite) do
26
23
  WebMock.disable_net_connect!(allow_localhost: true, net_http_connect_on_start: true)
24
+ Ridley::RSpec::ChefServer.start
27
25
  end
28
26
 
27
+ config.before(:all) { Ridley.logger = Celluloid.logger = nil }
28
+
29
29
  config.before(:each) do
30
30
  Celluloid.shutdown
31
31
  Celluloid.boot
@@ -3,8 +3,6 @@ require_relative 'spec_helpers'
3
3
 
4
4
  module Ridley::RSpec
5
5
  module ChefServer
6
- PORT = 8889
7
-
8
6
  class << self
9
7
  include Ridley::SpecHelpers
10
8
 
@@ -17,7 +15,7 @@ module Ridley::RSpec
17
15
  end
18
16
 
19
17
  def server
20
- @server ||= ChefZero::Server.new(port: PORT)
18
+ @server ||= ChefZero::Server.new(port: PORT, generate_real_keys: false)
21
19
  end
22
20
 
23
21
  def server_url
@@ -43,6 +41,10 @@ module Ridley::RSpec
43
41
  end
44
42
  end
45
43
 
44
+ include Ridley::SpecHelpers
45
+
46
+ PORT = 8889
47
+
46
48
  def chef_client(name, hash = Hash.new)
47
49
  load_data(:clients, name, hash)
48
50
  end
@@ -67,6 +69,10 @@ module Ridley::RSpec
67
69
  load_data(:roles, name, hash)
68
70
  end
69
71
 
72
+ def chef_zero_connection
73
+ Ridley::Connection.new(ChefServer.server_url, "reset", fixtures_path.join('reset.pem').to_s)
74
+ end
75
+
70
76
  private
71
77
 
72
78
  def load_data(key, name, hash)
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Ridley::UnixTemplateBinding do
3
+ describe Ridley::BootstrapContext::Unix do
4
4
  let(:options) do
5
5
  {
6
6
  server_url: "https://api.opscode.com/organizations/vialstudios",
@@ -34,7 +34,7 @@ describe Ridley::UnixTemplateBinding do
34
34
  end
35
35
  end
36
36
 
37
- subject { Ridley::UnixTemplateBinding.new(options) }
37
+ subject { described_class.new(options) }
38
38
 
39
39
  describe "MixinMethods" do
40
40
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Ridley::WindowsTemplateBinding do
3
+ describe Ridley::BootstrapContext::Windows do
4
4
  let(:options) do
5
5
  {
6
6
  server_url: "https://api.opscode.com/organizations/vialstudios",
@@ -30,7 +30,7 @@ describe Ridley::WindowsTemplateBinding do
30
30
  end
31
31
  end
32
32
 
33
- subject { Ridley::WindowsTemplateBinding.new(options) }
33
+ subject { described_class.new(options) }
34
34
 
35
35
  describe "MixinMethods" do
36
36
  describe "#templates_path" do
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Ridley::BootstrapBinding do
3
+ describe Ridley::BootstrapContext::Base do
4
4
  let(:host) { "reset.riotgames.com" }
5
5
  let(:options) do
6
6
  {
@@ -13,11 +13,7 @@ describe Ridley::BootstrapBinding do
13
13
  end
14
14
 
15
15
  describe "ClassMethods" do
16
- subject do
17
- Class.new do
18
- include Ridley::BootstrapBinding
19
- end
20
- end
16
+ subject { described_class }
21
17
 
22
18
  describe ":included" do
23
19
  context "when a class includes Ridley::BootstrapBinding" do
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ridley::HostCommander do
4
+ describe "ClassMethods" do
5
+ subject { described_class }
6
+
7
+ describe "::connector_port_open?" do
8
+ let(:host) { "127.0.0.1" }
9
+ let(:port) { 22 }
10
+ let(:socket) { double(close: nil) }
11
+
12
+ before { TCPSocket.stub(:new).and_return(socket) }
13
+
14
+ subject(:result) { described_class.connector_port_open?(host, port) }
15
+
16
+ context "when a port is open" do
17
+ it { should be_true }
18
+
19
+ it "closes the opened socket" do
20
+ socket.should_receive(:close)
21
+ result
22
+ end
23
+ end
24
+
25
+ context "when a port is closed" do
26
+ before { TCPSocket.stub(:new).and_raise(Errno::ECONNREFUSED) }
27
+
28
+ it { should be_false }
29
+ end
30
+
31
+ context "when host is unreachable" do
32
+ before { TCPSocket.stub(:new).and_raise(SocketError) }
33
+
34
+ it { should be_false }
35
+ end
36
+ end
37
+ end
38
+
39
+ subject { described_class.new }
40
+
41
+ describe "#run" do
42
+ let(:host) { "reset.riotgames.com" }
43
+ let(:command) { "ls" }
44
+ let(:options) do
45
+ { ssh: { port: 22 }, winrm: { port: 5985 } }
46
+ end
47
+
48
+ context "when communicating to a unix node" do
49
+ before do
50
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(false)
51
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(true)
52
+ end
53
+
54
+ it "sends a #run message to the ssh host connector" do
55
+ subject.send(:ssh).should_receive(:run).with(host, command, options)
56
+
57
+ subject.run(host, command, options)
58
+ end
59
+ end
60
+
61
+ context "when communicating to a windows node" do
62
+ before do
63
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(true)
64
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(false)
65
+ end
66
+
67
+ it "sends a #run message to the ssh host connector" do
68
+ subject.send(:winrm).should_receive(:run).with(host, command, options)
69
+
70
+ subject.run(host, command, options)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#bootstrap" do
76
+ let(:host) { "reset.riotgames.com" }
77
+ let(:options) do
78
+ { ssh: { port: 22 }, winrm: { port: 5985 } }
79
+ end
80
+
81
+ context "when communicating to a unix node" do
82
+ before do
83
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(false)
84
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(true)
85
+ end
86
+
87
+ it "sends a #bootstrap message to the ssh host connector" do
88
+ subject.send(:ssh).should_receive(:bootstrap).with(host, options)
89
+
90
+ subject.bootstrap(host, options)
91
+ end
92
+ end
93
+
94
+ context "when communicating to a windows node" do
95
+ before do
96
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(true)
97
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(false)
98
+ end
99
+
100
+ it "sends a #bootstrap message to the ssh host connector" do
101
+ subject.send(:winrm).should_receive(:bootstrap).with(host, options)
102
+
103
+ subject.bootstrap(host, options)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#chef_client" do
109
+ let(:host) { "reset.riotgames.com" }
110
+ let(:options) do
111
+ { ssh: { port: 22 }, winrm: { port: 5985 } }
112
+ end
113
+
114
+ context "when communicating to a unix node" do
115
+ before do
116
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(false)
117
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(true)
118
+ end
119
+
120
+ it "sends a #chef_client message to the ssh host connector" do
121
+ subject.send(:ssh).should_receive(:chef_client).with(host, options)
122
+
123
+ subject.chef_client(host, options)
124
+ end
125
+ end
126
+
127
+ context "when communicating to a windows node" do
128
+ before do
129
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(true)
130
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(false)
131
+ end
132
+
133
+ it "sends a #chef_client message to the ssh host connector" do
134
+ subject.send(:winrm).should_receive(:chef_client).with(host, options)
135
+
136
+ subject.chef_client(host, options)
137
+ end
138
+ end
139
+ end
140
+
141
+ describe "#put_secret" do
142
+ let(:host) { "reset.riotgames.com" }
143
+ let(:secret) { "something_secret" }
144
+ let(:options) do
145
+ { ssh: { port: 22 }, winrm: { port: 5985 } }
146
+ end
147
+
148
+ context "when communicating to a unix node" do
149
+ before do
150
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(false)
151
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(true)
152
+ end
153
+
154
+ it "sends a #put_secret message to the ssh host connector" do
155
+ subject.send(:ssh).should_receive(:put_secret).with(host, secret, options)
156
+
157
+ subject.put_secret(host, secret, options)
158
+ end
159
+ end
160
+
161
+ context "when communicating to a windows node" do
162
+ before do
163
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(true)
164
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(false)
165
+ end
166
+
167
+ it "sends a #put_secret message to the ssh host connector" do
168
+ subject.send(:winrm).should_receive(:put_secret).with(host, secret, options)
169
+
170
+ subject.put_secret(host, secret, options)
171
+ end
172
+ end
173
+ end
174
+
175
+ describe "#ruby_script" do
176
+ let(:host) { "reset.riotgames.com" }
177
+ let(:command_lines) { ["line one"] }
178
+ let(:options) do
179
+ { ssh: { port: 22 }, winrm: { port: 5985 } }
180
+ end
181
+
182
+ context "when communicating to a unix node" do
183
+ before do
184
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(false)
185
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(true)
186
+ end
187
+
188
+ it "sends a #ruby_script message to the ssh host connector" do
189
+ subject.send(:ssh).should_receive(:ruby_script).with(host, command_lines, options)
190
+
191
+ subject.ruby_script(host, command_lines, options)
192
+ end
193
+ end
194
+
195
+ context "when communicating to a windows node" do
196
+ before do
197
+ described_class.stub(:connector_port_open?).with(host, options[:winrm][:port]).and_return(true)
198
+ described_class.stub(:connector_port_open?).with(host, options[:ssh][:port], anything).and_return(false)
199
+ end
200
+
201
+ it "sends a #ruby_script message to the ssh host connector" do
202
+ subject.send(:winrm).should_receive(:ruby_script).with(host, command_lines, options)
203
+
204
+ subject.ruby_script(host, command_lines, options)
205
+ end
206
+ end
207
+ end
208
+ end