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.
- data/Gemfile +1 -1
- data/lib/ridley.rb +3 -3
- data/lib/ridley/bootstrap_context.rb +100 -0
- data/lib/ridley/bootstrap_context/unix.rb +74 -0
- data/lib/ridley/bootstrap_context/windows.rb +120 -0
- data/lib/ridley/chef_objects/node_object.rb +8 -5
- data/lib/ridley/host_commander.rb +207 -0
- data/lib/ridley/host_connector.rb +49 -87
- data/lib/ridley/host_connector/ssh.rb +153 -39
- data/lib/ridley/host_connector/winrm.rb +164 -39
- data/lib/ridley/resources/node_resource.rb +52 -56
- data/lib/ridley/version.rb +1 -1
- data/ridley.gemspec +0 -2
- data/spec/spec_helper.rb +4 -4
- data/spec/support/chef_server.rb +9 -3
- data/spec/unit/ridley/{bootstrap_bindings/unix_template_binding_spec.rb → bootstrap_context/unix_spec.rb} +2 -2
- data/spec/unit/ridley/{bootstrap_bindings/windows_template_binding_spec.rb → bootstrap_context/windows_spec.rb} +2 -2
- data/spec/unit/ridley/{mixin/bootstrap_binding_spec.rb → bootstrap_context_spec.rb} +2 -6
- data/spec/unit/ridley/host_commander_spec.rb +208 -0
- data/spec/unit/ridley/host_connector/ssh_spec.rb +37 -31
- data/spec/unit/ridley/host_connector/winrm_spec.rb +124 -31
- data/spec/unit/ridley/host_connector_spec.rb +23 -147
- data/spec/unit/ridley/resources/node_resource_spec.rb +55 -115
- metadata +17 -66
- data/lib/ridley/bootstrap_bindings.rb +0 -3
- data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +0 -108
- data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +0 -163
- data/lib/ridley/bootstrapper.rb +0 -89
- data/lib/ridley/bootstrapper/context.rb +0 -81
- data/lib/ridley/host_connector/response_set.rb +0 -98
- data/lib/ridley/host_connector/ssh/worker.rb +0 -135
- data/lib/ridley/host_connector/winrm/worker.rb +0 -159
- data/lib/ridley/log.rb +0 -10
- data/lib/ridley/mixin/bootstrap_binding.rb +0 -77
- data/spec/unit/ridley/bootstrapper/context_spec.rb +0 -45
- data/spec/unit/ridley/bootstrapper_spec.rb +0 -96
- data/spec/unit/ridley/host_connector/response_set_spec.rb +0 -112
- data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +0 -57
- data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +0 -139
@@ -1,51 +1,57 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Ridley::HostConnector::SSH do
|
4
|
-
|
5
|
-
|
6
|
-
let(:node_one) do
|
7
|
-
Ridley::NodeObject.new(resource, automatic: { cloud: { public_hostname: "33.33.33.10" } })
|
8
|
-
end
|
9
|
-
|
10
|
-
let(:node_two) do
|
11
|
-
Ridley::NodeObject.new(resource, automatic: { cloud: { public_hostname: "33.33.33.11" } })
|
12
|
-
end
|
4
|
+
subject { connector }
|
5
|
+
let(:connector) { described_class.new }
|
13
6
|
|
7
|
+
let(:host) { 'reset.riotgames.com' }
|
14
8
|
let(:options) do
|
15
9
|
{
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
server_url: double('server_url'),
|
11
|
+
validator_path: fixtures_path.join('reset.pem'),
|
12
|
+
validator_client: double('validator_client'),
|
13
|
+
encrypted_data_bag_secret: 'encrypted_data_bag_secret',
|
14
|
+
ssh: Hash.new,
|
15
|
+
chef_version: double('chef_version')
|
19
16
|
}
|
20
17
|
end
|
21
18
|
|
22
|
-
describe "
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
it "raises a LocalJumpError if a block is not provided" do
|
27
|
-
expect {
|
28
|
-
subject.start([node_one, node_two], options)
|
29
|
-
}.to raise_error(LocalJumpError)
|
30
|
-
end
|
19
|
+
describe "#bootstrap" do
|
20
|
+
it "sends a #run message to self to bootstrap a node" do
|
21
|
+
connector.should_receive(:run).with(host, anything, options)
|
22
|
+
connector.bootstrap(host, options)
|
31
23
|
end
|
32
24
|
end
|
33
25
|
|
34
|
-
|
35
|
-
|
26
|
+
describe "#chef_client" do
|
27
|
+
it "sends a #run message to self to execute chef-client" do
|
28
|
+
connector.should_receive(:run).with(host, "chef-client", options)
|
29
|
+
connector.chef_client(host, options)
|
30
|
+
end
|
36
31
|
end
|
37
32
|
|
38
|
-
describe "#
|
39
|
-
let(:
|
40
|
-
let(:
|
41
|
-
before { Ridley::HostConnector::SSH::Worker.stub(:new).and_return(worker) }
|
33
|
+
describe "#put_secret" do
|
34
|
+
let(:encrypted_data_bag_secret_path) { fixtures_path.join("encrypted_data_bag_secret").to_s }
|
35
|
+
let(:secret) { File.read(encrypted_data_bag_secret_path).chomp }
|
42
36
|
|
43
|
-
|
44
|
-
|
37
|
+
it "receives a run command with echo" do
|
38
|
+
connector.should_receive(:run).with(host,
|
39
|
+
"echo '#{secret}' > /etc/chef/encrypted_data_bag_secret; chmod 0600 /etc/chef/encrypted_data_bag_secret",
|
40
|
+
options
|
41
|
+
)
|
42
|
+
connector.put_secret(host, secret, options)
|
45
43
|
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#ruby_script" do
|
47
|
+
let(:command_lines) { ["puts 'hello'", "puts 'there'"] }
|
46
48
|
|
47
|
-
it "
|
48
|
-
|
49
|
+
it "receives a ruby call with the command" do
|
50
|
+
connector.should_receive(:run).with(host,
|
51
|
+
"#{described_class::EMBEDDED_RUBY_PATH} -e \"puts 'hello';puts 'there'\"",
|
52
|
+
options
|
53
|
+
)
|
54
|
+
connector.ruby_script(host, command_lines, options)
|
49
55
|
end
|
50
56
|
end
|
51
57
|
end
|
@@ -1,52 +1,145 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Ridley::HostConnector::WinRM do
|
4
|
-
|
5
|
-
|
6
|
-
let(:
|
7
|
-
|
4
|
+
subject { connector }
|
5
|
+
let(:connector) { described_class.new }
|
6
|
+
let(:host) { 'reset.riotgames.com' }
|
7
|
+
let(:options) do
|
8
|
+
{
|
9
|
+
server_url: double('server_url'),
|
10
|
+
validator_path: fixtures_path.join('reset.pem'),
|
11
|
+
validator_client: double('validator_client'),
|
12
|
+
encrypted_data_bag_secret: 'encrypted_data_bag_secret',
|
13
|
+
winrm: Hash.new,
|
14
|
+
chef_version: double('chef_version')
|
15
|
+
}
|
8
16
|
end
|
9
17
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
18
|
+
before { described_class::CommandUploader.stub(:new).and_return(double('command_uploader')) }
|
19
|
+
|
20
|
+
describe "#get_command" do
|
21
|
+
subject(:get_command) { connector.get_command(command, command_uploader_stub) }
|
22
|
+
|
23
|
+
let(:command) { "echo %TEMP%" }
|
24
|
+
let(:command_uploader_stub) { double('CommandUploader') }
|
25
|
+
|
26
|
+
it { should eq(command) }
|
14
27
|
|
15
|
-
|
16
|
-
|
28
|
+
context "when a command is more than 2047 characters" do
|
29
|
+
let(:command) { "a" * 2048 }
|
30
|
+
|
31
|
+
it "uploads and returns a command" do
|
32
|
+
described_class::CommandUploader.stub(new: command_uploader_stub)
|
33
|
+
|
34
|
+
command_uploader_stub.should_receive :upload
|
35
|
+
command_uploader_stub.stub command: "my command"
|
36
|
+
command_uploader_stub.stub(:cleanup)
|
37
|
+
|
38
|
+
get_command.should eq("my command")
|
39
|
+
end
|
40
|
+
end
|
17
41
|
end
|
18
42
|
|
19
|
-
describe "
|
20
|
-
subject {
|
43
|
+
describe "#run" do
|
44
|
+
subject(:result) { connector.run(host, command, options) }
|
45
|
+
let(:command) { "dir" }
|
46
|
+
let(:command_uploader_stub) { double('CommandUploader', cleanup: true) }
|
47
|
+
let(:stdout) { "stdout" }
|
48
|
+
let(:stderr) { nil }
|
49
|
+
let(:winrm_stub) { double }
|
50
|
+
|
51
|
+
before do
|
52
|
+
described_class::CommandUploader.stub(:new).and_return(command_uploader_stub)
|
53
|
+
connector.stub(:winrm).and_return(winrm_stub)
|
54
|
+
winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_return(exitcode: 0)
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when the exit_code is 0" do
|
58
|
+
it "returns a non-error HostConnector::Response" do
|
59
|
+
expect(result).to be_a(Ridley::HostConnector::Response)
|
60
|
+
expect(result).to_not be_error
|
61
|
+
end
|
62
|
+
|
63
|
+
it "sets the response's stdout message" do
|
64
|
+
expect(result.stdout).to eq("stdout")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when the exit_code is not 0" do
|
69
|
+
let(:stderr) { "stderr" }
|
70
|
+
|
71
|
+
before do
|
72
|
+
winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_return(exitcode: 1)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns an error HostConnector::Response with an error" do
|
76
|
+
expect(result).to be_a(Ridley::HostConnector::Response)
|
77
|
+
expect(result).to be_error
|
78
|
+
end
|
21
79
|
|
22
|
-
|
23
|
-
|
24
|
-
{
|
25
|
-
user: "Administrator",
|
26
|
-
password: "password1"
|
27
|
-
}
|
80
|
+
it "sets the response's stderr message" do
|
81
|
+
expect(result.stderr).to eq("stderr")
|
28
82
|
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when a WinRM::WinRMHTTPTransportError error is raised" do
|
86
|
+
let(:stderr) { "error" }
|
87
|
+
before { winrm_stub.stub(:run_cmd).and_yield(stdout, stderr).and_raise(::WinRM::WinRMHTTPTransportError) }
|
29
88
|
|
30
|
-
it "
|
31
|
-
result
|
32
|
-
|
33
|
-
end
|
34
|
-
result.should be_a(Ridley::HostConnector::ResponseSet)
|
89
|
+
it "returns an error HostConnector::Response with an error" do
|
90
|
+
expect(result).to be_a(Ridley::HostConnector::Response)
|
91
|
+
expect(result).to be_error
|
35
92
|
end
|
36
93
|
|
37
|
-
it "
|
38
|
-
expect
|
39
|
-
subject.start([node_one, node_two], options)
|
40
|
-
}.to raise_error(LocalJumpError)
|
94
|
+
it "sets the response's stderr message to the exception's message" do
|
95
|
+
expect(result.stderr).to eql("WinRM::WinRMHTTPTransportError")
|
41
96
|
end
|
42
97
|
end
|
43
98
|
end
|
44
99
|
|
45
|
-
|
100
|
+
describe "#bootstrap" do
|
101
|
+
it "sends a #run message to self to bootstrap a node" do
|
102
|
+
connector.should_receive(:run).with(host, anything, options)
|
103
|
+
connector.bootstrap(host, options)
|
104
|
+
end
|
105
|
+
end
|
46
106
|
|
47
|
-
describe "#
|
48
|
-
|
49
|
-
|
107
|
+
describe "#chef_client" do
|
108
|
+
subject(:chef_client) { connector.chef_client(host, options) }
|
109
|
+
|
110
|
+
it "receives a command to run chef-client" do
|
111
|
+
connector.should_receive(:run).with(host, "chef-client", options)
|
112
|
+
|
113
|
+
chef_client
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#put_secret" do
|
118
|
+
subject(:put_secret) { connector.put_secret(host, secret, options) }
|
119
|
+
let(:encrypted_data_bag_secret_path) { fixtures_path.join("encrypted_data_bag_secret").to_s }
|
120
|
+
let(:secret) { File.read(encrypted_data_bag_secret_path).chomp }
|
121
|
+
|
122
|
+
it "receives a command to copy the secret" do
|
123
|
+
connector.should_receive(:run).with(host,
|
124
|
+
"echo #{secret} > C:\\chef\\encrypted_data_bag_secret",
|
125
|
+
options
|
126
|
+
)
|
127
|
+
|
128
|
+
put_secret
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#ruby_script" do
|
133
|
+
subject(:ruby_script) { connector.ruby_script(host, command_lines, options) }
|
134
|
+
let(:command_lines) { ["puts 'hello'", "puts 'there'"] }
|
135
|
+
|
136
|
+
it "receives a ruby call with the command" do
|
137
|
+
connector.should_receive(:run).with(host,
|
138
|
+
"#{described_class::EMBEDDED_RUBY_PATH} -e \"puts 'hello';puts 'there'\"",
|
139
|
+
options
|
140
|
+
)
|
141
|
+
|
142
|
+
ruby_script
|
50
143
|
end
|
51
144
|
end
|
52
145
|
end
|
@@ -1,168 +1,44 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Ridley::HostConnector do
|
4
|
-
subject
|
5
|
-
described_class
|
6
|
-
end
|
7
|
-
|
8
|
-
it "returns 22 as the default SSH port" do
|
9
|
-
described_class::DEFAULT_SSH_PORT.should eq(22)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "returns 5985 as the default WinRM port" do
|
13
|
-
described_class::DEFAULT_WINRM_PORT.should eq(5985)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "::new" do
|
17
|
-
let(:host) { "192.168.1.1" }
|
18
|
-
let(:options) do
|
19
|
-
{
|
20
|
-
ssh: {
|
21
|
-
user: "reset",
|
22
|
-
password: "lol"
|
23
|
-
},
|
24
|
-
winrm: {
|
25
|
-
user: "Administrator",
|
26
|
-
password: "secret"
|
27
|
-
}
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
subject { described_class.new(host, options) }
|
3
|
+
describe Ridley::HostConnector::Base do
|
4
|
+
subject { Class.new(Ridley::HostConnector::Base).new }
|
32
5
|
|
33
|
-
|
34
|
-
|
35
|
-
described_class.stub(:best_connector_for).and_yield(Ridley::HostConnector::SSH)
|
36
|
-
end
|
6
|
+
let(:host) { double('host') }
|
7
|
+
let(:options) { Hash.new }
|
37
8
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when the best connector is WinRM" do
|
43
|
-
before do
|
44
|
-
described_class.stub(:best_connector_for).and_yield(Ridley::HostConnector::WinRM)
|
45
|
-
end
|
9
|
+
describe "#run" do
|
10
|
+
let(:command) { double('command') }
|
46
11
|
|
47
|
-
|
48
|
-
|
49
|
-
its(:password) { should eq("secret") }
|
12
|
+
it "raises a RuntimeError" do
|
13
|
+
expect { subject.run(host, command, options) }.to raise_error(RuntimeError)
|
50
14
|
end
|
51
15
|
end
|
52
16
|
|
53
|
-
describe "
|
54
|
-
|
55
|
-
|
56
|
-
let(:socket) { double(:new => true, :close => nil) }
|
57
|
-
|
58
|
-
context "when a port is open" do
|
59
|
-
before do
|
60
|
-
TCPSocket.stub(:new).and_return(socket)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "returns true" do
|
64
|
-
subject.connector_port_open?(host, port).should eql(true)
|
65
|
-
end
|
66
|
-
|
67
|
-
it "closes the opened socket" do
|
68
|
-
socket.should_receive(:close)
|
69
|
-
subject.connector_port_open?(host, port)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when a port is closed" do
|
74
|
-
before do
|
75
|
-
TCPSocket.stub(:new).and_raise(Errno::ECONNREFUSED)
|
76
|
-
end
|
77
|
-
|
78
|
-
it "returns false" do
|
79
|
-
subject.connector_port_open?(host, port).should eq(false)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "when host is unreachable" do
|
84
|
-
before do
|
85
|
-
TCPSocket.stub(:new).and_raise(SocketError)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "returns false" do
|
89
|
-
subject.connector_port_open?(host, port).should eql(false)
|
90
|
-
end
|
17
|
+
describe "#bootstrap" do
|
18
|
+
it "raises a RuntimeError" do
|
19
|
+
expect { subject.bootstrap(host, options) }.to raise_error(RuntimeError)
|
91
20
|
end
|
92
21
|
end
|
93
22
|
|
94
|
-
describe "
|
95
|
-
|
96
|
-
|
97
|
-
context "when an SSH port is open" do
|
98
|
-
it "returns Ridley::HostConnector::SSH" do
|
99
|
-
subject.stub(:connector_port_open?).and_return(false, true)
|
100
|
-
expect(subject.best_connector_for(host)).to eq(Ridley::HostConnector::SSH)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context "when an SSH port isnt open and a WinRM port is open" do
|
105
|
-
it "retrns Ridley::HostConnector::WinRM" do
|
106
|
-
subject.stub(:connector_port_open?).and_return(true, false)
|
107
|
-
expect(subject.best_connector_for(host)).to eq(Ridley::HostConnector::WinRM)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
context "when no useable ports are open" do
|
112
|
-
it "raises an exception" do
|
113
|
-
subject.stub(:connector_port_open?).and_return(false, false)
|
114
|
-
expect {
|
115
|
-
subject.best_connector_for(host)
|
116
|
-
}.to raise_error(Ridley::Errors::HostConnectionError)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context "when a block is provided" do
|
121
|
-
it "yields the best HostConnector to the block" do
|
122
|
-
subject.stub(:connector_port_open?).and_return(false, true)
|
123
|
-
subject.best_connector_for(host) do |yielded|
|
124
|
-
expect(yielded).to eq(Ridley::HostConnector::SSH)
|
125
|
-
end
|
126
|
-
end
|
23
|
+
describe "#chef_client" do
|
24
|
+
it "raises a RuntimeError" do
|
25
|
+
expect { subject.chef_client(host, options) }.to raise_error(RuntimeError)
|
127
26
|
end
|
128
27
|
end
|
129
28
|
|
130
|
-
describe "
|
131
|
-
let(:
|
132
|
-
{
|
133
|
-
ssh: {
|
134
|
-
port: 1234
|
135
|
-
},
|
136
|
-
winrm: {
|
137
|
-
port: 5678
|
138
|
-
}
|
139
|
-
}
|
140
|
-
end
|
29
|
+
describe "#put_secret" do
|
30
|
+
let(:secret) { double('secret') }
|
141
31
|
|
142
|
-
|
143
|
-
|
144
|
-
subject.parse_port_options(options).should include(1234)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
context "when there is no :ssh key" do
|
149
|
-
it "returns the default value for port" do
|
150
|
-
options.delete(:ssh)
|
151
|
-
subject.parse_port_options(options).should include(22)
|
152
|
-
end
|
32
|
+
it "raises a RuntimeError" do
|
33
|
+
expect { subject.put_secret(host, secret, options) }.to raise_error(RuntimeError)
|
153
34
|
end
|
35
|
+
end
|
154
36
|
|
155
|
-
|
156
|
-
|
157
|
-
subject.parse_port_options(options).should include(5678)
|
158
|
-
end
|
159
|
-
end
|
37
|
+
describe "#ruby_script" do
|
38
|
+
let(:command_lines) { double('command-lines') }
|
160
39
|
|
161
|
-
|
162
|
-
|
163
|
-
options.delete(:winrm)
|
164
|
-
subject.parse_port_options(options).should include(5985)
|
165
|
-
end
|
40
|
+
it "raises a RuntimeError" do
|
41
|
+
expect { subject.ruby_script(host, command_lines, options) }.to raise_error(RuntimeError)
|
166
42
|
end
|
167
43
|
end
|
168
44
|
end
|