ridley 0.12.4 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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