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.
- 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
|