nodespec 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +90 -0
- data/LICENSE.md +21 -0
- data/README.md +107 -0
- data/Rakefile +5 -0
- data/lib/nodespec/backend_proxy/base.rb +20 -0
- data/lib/nodespec/backend_proxy/cmd.rb +9 -0
- data/lib/nodespec/backend_proxy/exec.rb +21 -0
- data/lib/nodespec/backend_proxy/ssh.rb +28 -0
- data/lib/nodespec/backend_proxy/unixshell_utility.rb +32 -0
- data/lib/nodespec/backend_proxy/winrm.rb +23 -0
- data/lib/nodespec/backends.rb +13 -0
- data/lib/nodespec/command_execution.rb +16 -0
- data/lib/nodespec/communication_adapters/aws_ec2.rb +24 -0
- data/lib/nodespec/communication_adapters/local_backend.rb +15 -0
- data/lib/nodespec/communication_adapters/native_communicator.rb +32 -0
- data/lib/nodespec/communication_adapters/remote_backend.rb +15 -0
- data/lib/nodespec/communication_adapters/ssh.rb +14 -0
- data/lib/nodespec/communication_adapters/ssh_communicator.rb +54 -0
- data/lib/nodespec/communication_adapters/vagrant.rb +37 -0
- data/lib/nodespec/communication_adapters/winrm.rb +13 -0
- data/lib/nodespec/communication_adapters/winrm_communicator.rb +65 -0
- data/lib/nodespec/communication_adapters.rb +22 -0
- data/lib/nodespec/local_command_runner.rb +17 -0
- data/lib/nodespec/node.rb +56 -0
- data/lib/nodespec/node_configurations.rb +29 -0
- data/lib/nodespec/provisioning/ansible.rb +96 -0
- data/lib/nodespec/provisioning/chef.rb +68 -0
- data/lib/nodespec/provisioning/puppet.rb +55 -0
- data/lib/nodespec/provisioning/shellscript.rb +19 -0
- data/lib/nodespec/provisioning.rb +14 -0
- data/lib/nodespec/run_options.rb +14 -0
- data/lib/nodespec/runtime_gem_loader.rb +19 -0
- data/lib/nodespec/shared_examples_support.rb +13 -0
- data/lib/nodespec/verbose_output.rb +9 -0
- data/lib/nodespec/version.rb +3 -0
- data/nodespec.gemspec +28 -0
- data/spec/backend_proxy/base_spec.rb +29 -0
- data/spec/backend_proxy/exec_spec.rb +34 -0
- data/spec/backend_proxy/ssh_spec.rb +32 -0
- data/spec/backend_proxy/unixshell_utility_spec.rb +29 -0
- data/spec/backend_proxy/winrm_spec.rb +34 -0
- data/spec/command_execution_spec.rb +36 -0
- data/spec/communication_adapters/aws_ec2_spec.rb +70 -0
- data/spec/communication_adapters/local_backend_spec.rb +38 -0
- data/spec/communication_adapters/native_communicator_spec.rb +53 -0
- data/spec/communication_adapters/remote_backend_spec.rb +46 -0
- data/spec/communication_adapters/ssh_communicator_spec.rb +121 -0
- data/spec/communication_adapters/ssh_spec.rb +18 -0
- data/spec/communication_adapters/vagrant_spec.rb +61 -0
- data/spec/communication_adapters/winrm_communicator_spec.rb +111 -0
- data/spec/communication_adapters/winrm_spec.rb +18 -0
- data/spec/communication_adapters_spec.rb +29 -0
- data/spec/local_command_runner_spec.rb +26 -0
- data/spec/node_configurations_spec.rb +41 -0
- data/spec/node_spec.rb +110 -0
- data/spec/provisioning/ansible_spec.rb +143 -0
- data/spec/provisioning/chef_spec.rb +87 -0
- data/spec/provisioning/puppet_spec.rb +54 -0
- data/spec/provisioning/shellscript_spec.rb +20 -0
- data/spec/provisioning_spec.rb +52 -0
- data/spec/runtime_gem_loader_spec.rb +33 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/backend.rb +10 -0
- data/spec/support/init_with_current_node.rb +4 -0
- data/spec/support/local_command.rb +12 -0
- data/spec/support/node_command.rb +12 -0
- data/spec/support/ssh_communicator.rb +9 -0
- data/spec/support/winrm_communicator.rb +9 -0
- metadata +105 -3
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'nodespec/backend_proxy/winrm'
|
2
|
+
|
3
|
+
module NodeSpec
|
4
|
+
module BackendProxy
|
5
|
+
describe WinRM do
|
6
|
+
let(:winrm) { double('winrm session') }
|
7
|
+
let(:subject) {WinRM.new(winrm)}
|
8
|
+
before do
|
9
|
+
allow(winrm).to receive(:set_timeout).with(NodeSpec::RunOptions.command_timeout)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns true upon successful execution' do
|
13
|
+
result = {exitcode: 0, data: [{stdout: 'output line 1'}, {stdout: 'output line 2'}]}
|
14
|
+
allow(winrm).to receive(:powershell).and_return(result)
|
15
|
+
|
16
|
+
expect(subject.execute('command')).to be_truthy
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns false if stderr not empty' do
|
20
|
+
result = {exitcode: 0, data: [{stdout: 'output line 1', stderr: 'error line 1'}, {stdout: 'output line 2', stderr: 'error line 2'}]}
|
21
|
+
allow(winrm).to receive(:powershell).and_return(result)
|
22
|
+
|
23
|
+
expect(subject.execute('command')).to be_falsy
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns false if exitcode not zero' do
|
27
|
+
result = {exitcode: 1, data: [{stdout: 'output line 1'}, {stdout: 'output line 2'}]}
|
28
|
+
allow(winrm).to receive(:powershell).and_return(result)
|
29
|
+
|
30
|
+
expect(subject.execute('command')).to be_falsy
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'nodespec/command_execution'
|
2
|
+
|
3
|
+
module NodeSpec
|
4
|
+
describe CommandExecution do
|
5
|
+
let(:subject) {Object.new.extend CommandExecution}
|
6
|
+
|
7
|
+
it 'does not raise an error if the command succeeds' do
|
8
|
+
subject.execute_within_timeout('test command') { true }
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises an error if the command fails' do
|
12
|
+
expect {
|
13
|
+
subject.execute_within_timeout('test command') { false }
|
14
|
+
}.to raise_error CommandExecution::CommandExecutionError
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'custom timeout' do
|
18
|
+
it 'fails if running longer than the set timeout' do
|
19
|
+
expect {
|
20
|
+
subject.execute_within_timeout('test command', 1) { sleep(2) }
|
21
|
+
}.to raise_error Timeout::Error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'preset timeout' do
|
26
|
+
before do
|
27
|
+
NodeSpec::RunOptions.command_timeout = 1
|
28
|
+
end
|
29
|
+
it 'fails if running longer than the set timeout' do
|
30
|
+
expect {
|
31
|
+
subject.execute_within_timeout('test command') { sleep(2) }
|
32
|
+
}.to raise_error Timeout::Error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'nodespec/communication_adapters/aws_ec2'
|
4
|
+
|
5
|
+
module NodeSpec
|
6
|
+
module CommunicationAdapters
|
7
|
+
describe AwsEc2 do
|
8
|
+
let(:ec2_instance) {double('ec2 instance')}
|
9
|
+
|
10
|
+
before do
|
11
|
+
instance_collection = double
|
12
|
+
allow(AWS).to receive_message_chain(:ec2, :instances).and_return(instance_collection)
|
13
|
+
allow(instance_collection).to receive(:[]).with('test-instance').and_return(ec2_instance)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'connecting to a running instance' do
|
17
|
+
before do
|
18
|
+
allow(ec2_instance).to receive(:exists?).ordered.and_return(true)
|
19
|
+
allow(ec2_instance).to receive(:status).ordered.and_return(:running)
|
20
|
+
allow(ec2_instance).to receive(:public_dns_name).ordered.and_return('test hostname')
|
21
|
+
end
|
22
|
+
|
23
|
+
%w[ssh winrm].each do |connection|
|
24
|
+
describe "#{connection} communicator" do
|
25
|
+
include_context "new_#{connection}_communicator", 'test hostname', 'test_os', 'foo' => 'bar'
|
26
|
+
|
27
|
+
it 'returns communicator with the instance name from the node name' do
|
28
|
+
expect(AwsEc2.communicator_for('test-instance', 'test_os', connection => {'foo' => 'bar'})).to eq("#{connection} communicator")
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns communicator with the instance name from the options' do
|
32
|
+
expect(AwsEc2.communicator_for('test_node', 'test_os', 'instance' => 'test-instance', connection => {'foo' => 'bar'})).to eq("#{connection} communicator")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'openssh default connection' do
|
38
|
+
include_context "new_ssh_communicator", 'test hostname', 'test_os', {}
|
39
|
+
|
40
|
+
it 'returns an ssh communicator' do
|
41
|
+
expect(AwsEc2.communicator_for('test-instance', 'test_os')).to eq("ssh communicator")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'connecting to an unreachable instance' do
|
47
|
+
context 'not existing instance' do
|
48
|
+
before do
|
49
|
+
allow(ec2_instance).to receive(:exists?).ordered.and_return(false)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises an error' do
|
53
|
+
expect {AwsEc2.communicator_for('test-instance', 'test_os', 'foo' => 'bar')}.to raise_error
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'not running instance' do
|
58
|
+
before do
|
59
|
+
allow(ec2_instance).to receive(:exists?).ordered.and_return(true)
|
60
|
+
allow(ec2_instance).to receive(:status).ordered.and_return(:whatever_else)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'raises an error' do
|
64
|
+
expect {AwsEc2.communicator_for('test-instance', 'test_os', 'foo' => 'bar')}.to raise_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/communication_adapters/local_backend'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe LocalBackend do
|
7
|
+
let(:subject) {Object.new.extend LocalBackend}
|
8
|
+
|
9
|
+
context 'no os' do
|
10
|
+
before do
|
11
|
+
def subject.os
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it_behaves_like 'providing a backend', 'Exec'
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'UN*X os' do
|
18
|
+
before do
|
19
|
+
def subject.os
|
20
|
+
'CentOS'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it_behaves_like 'providing a backend', 'Exec'
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'Windows os' do
|
28
|
+
before do
|
29
|
+
def subject.os
|
30
|
+
'Windows'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it_behaves_like 'providing a backend', 'Cmd'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'nodespec/communication_adapters/native_communicator'
|
2
|
+
|
3
|
+
module NodeSpec
|
4
|
+
module CommunicationAdapters
|
5
|
+
describe NativeCommunicator do
|
6
|
+
it 'provides a local backend' do
|
7
|
+
expect(NativeCommunicator.new).to be_a(LocalBackend)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
[nil, 'Test OS'].each do |os|
|
12
|
+
it 'holds the os information' do
|
13
|
+
expect(NativeCommunicator.new(os).os).to eq os
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#bind_to' do
|
19
|
+
let(:rspec_configuration) {double('rspec configuration')}
|
20
|
+
|
21
|
+
context('ssh session') do
|
22
|
+
let(:ssh_session) {double('ssh session')}
|
23
|
+
|
24
|
+
before do
|
25
|
+
allow(rspec_configuration).to receive(:ssh).and_return(ssh_session)
|
26
|
+
allow(rspec_configuration).to receive(:winrm)
|
27
|
+
[:close, :host].each {|m| allow(ssh_session).to receive(m)}
|
28
|
+
allow(ssh_session).to receive(:options).and_return({port: 'port'})
|
29
|
+
expect(rspec_configuration).to receive(:ssh=).with(nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'closes and removes an existing ssh session' do
|
33
|
+
subject.bind_to(rspec_configuration)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context('winrm session') do
|
38
|
+
let(:winrm_session) {double('winrm session')}
|
39
|
+
|
40
|
+
before do
|
41
|
+
allow(rspec_configuration).to receive(:ssh)
|
42
|
+
allow(rspec_configuration).to receive(:winrm).and_return(winrm_session)
|
43
|
+
expect(rspec_configuration).to receive(:winrm=).with(nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'removes an existing winrm session' do
|
47
|
+
subject.bind_to(rspec_configuration)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/communication_adapters/remote_backend'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe RemoteBackend do
|
7
|
+
let(:subject) {
|
8
|
+
Object.new.tap do |obj|
|
9
|
+
obj.extend RemoteBackend
|
10
|
+
def obj.session
|
11
|
+
'session'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
context 'no os' do
|
17
|
+
before do
|
18
|
+
def subject.os
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it_behaves_like 'providing a backend', 'Ssh'
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'UN*X os' do
|
26
|
+
before do
|
27
|
+
def subject.os
|
28
|
+
'CentOS'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it_behaves_like 'providing a backend', 'Ssh'
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'Windows os' do
|
36
|
+
before do
|
37
|
+
def subject.os
|
38
|
+
'Windows'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it_behaves_like 'providing a backend', 'WinRM'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'nodespec/communication_adapters/ssh_communicator'
|
2
|
+
|
3
|
+
module NodeSpec
|
4
|
+
module CommunicationAdapters
|
5
|
+
describe SshCommunicator do
|
6
|
+
let(:rspec_configuration) {double('rspec configuration')}
|
7
|
+
let(:ssh_session) {double('ssh session')}
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Net::SSH).to receive(:start).with('test.host.name', 'testuser', port: 1234, password: 'testpassword', keys: 'testkeys').and_return('new session')
|
11
|
+
end
|
12
|
+
|
13
|
+
shared_context 'existing session' do |hostname, port|
|
14
|
+
before do
|
15
|
+
allow(rspec_configuration).to receive(:ssh).and_return(ssh_session)
|
16
|
+
allow(ssh_session).to receive(:host).and_return(hostname)
|
17
|
+
allow(ssh_session).to receive(:options).and_return({port: port})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
shared_examples 'creating new session' do
|
22
|
+
before do
|
23
|
+
expect(rspec_configuration).to receive(:ssh=).with('new session')
|
24
|
+
expect(rspec_configuration).to receive(:host=).with('test.host.name')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates and holds a new session' do
|
28
|
+
subject.bind_to(rspec_configuration)
|
29
|
+
|
30
|
+
expect(subject.session).to eq('new session')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
shared_examples 'binding to configuration' do
|
35
|
+
before do
|
36
|
+
allow(rspec_configuration).to receive(:winrm)
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'existing winrm session' do
|
40
|
+
before do
|
41
|
+
allow(rspec_configuration).to receive(:winrm).and_return('winrm')
|
42
|
+
allow(rspec_configuration).to receive(:ssh).and_return(nil)
|
43
|
+
expect(rspec_configuration).to receive(:winrm=).with(nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
include_examples 'creating new session'
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'no existing ssh session' do
|
50
|
+
before do
|
51
|
+
allow(rspec_configuration).to receive(:ssh).and_return(nil)
|
52
|
+
end
|
53
|
+
|
54
|
+
include_examples 'creating new session'
|
55
|
+
end
|
56
|
+
|
57
|
+
{'another host' => 1234, 'test.host.name' => 5678}.each do |hostname, port|
|
58
|
+
context 'existing session with different connection' do
|
59
|
+
include_context 'existing session', hostname, port
|
60
|
+
before do
|
61
|
+
expect(ssh_session).to receive(:close)
|
62
|
+
allow(ssh_session).to receive(:closed?).and_return(true)
|
63
|
+
end
|
64
|
+
include_examples 'creating new session'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'existing ssh session with same connection' do
|
69
|
+
include_context 'existing session', 'test.host.name', 1234
|
70
|
+
context 'open session' do
|
71
|
+
before { allow(ssh_session).to receive(:closed?).and_return(false) }
|
72
|
+
|
73
|
+
it 'does not change the current rspec configuration' do
|
74
|
+
expect(Net::SSH).not_to receive(:start)
|
75
|
+
expect(rspec_configuration).not_to receive(:ssh=)
|
76
|
+
expect(rspec_configuration).not_to receive(:host=)
|
77
|
+
|
78
|
+
subject.bind_to(rspec_configuration)
|
79
|
+
|
80
|
+
expect(subject.session).to eq(ssh_session)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'closed session' do
|
85
|
+
before { allow(ssh_session).to receive(:closed?).and_return(true) }
|
86
|
+
include_examples 'creating new session'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'with given credentials' do
|
92
|
+
let(:subject) {SshCommunicator.new('test.host.name', nil, 'port' => 1234, 'user' => 'testuser', 'password' => 'testpassword', 'keys' => 'testkeys')}
|
93
|
+
before do
|
94
|
+
allow(Net::SSH).to receive(:configuration_for).and_return({})
|
95
|
+
end
|
96
|
+
include_examples 'binding to configuration'
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'credentials from OpenSSH config files' do
|
100
|
+
let(:subject) {SshCommunicator.new('test.host.name', nil, 'port' => 1234, 'user' => 'testuser')}
|
101
|
+
before do
|
102
|
+
allow(Net::SSH).to receive(:configuration_for).with('test.host.name').and_return(password: 'testpassword', keys: 'testkeys')
|
103
|
+
end
|
104
|
+
|
105
|
+
include_examples 'binding to configuration'
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'provides a remote backend' do
|
109
|
+
expect(SshCommunicator.new('test.host.name')).to be_a(RemoteBackend)
|
110
|
+
end
|
111
|
+
|
112
|
+
describe '#initialize' do
|
113
|
+
[nil, 'Test OS'].each do |os|
|
114
|
+
it 'holds the os information' do
|
115
|
+
expect(SshCommunicator.new('test.host.name', os, {}).os).to eq os
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/communication_adapters/ssh'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe Ssh do
|
7
|
+
include_context 'new_ssh_communicator', 'test.host.name', 'test_os', {'foo' => 'bar'}
|
8
|
+
|
9
|
+
it 'returns communicator with the host name from the node name' do
|
10
|
+
expect(Ssh.communicator_for('test.host.name', 'test_os', 'foo' => 'bar')).to eq('ssh communicator')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns communicator with the host name from the options' do
|
14
|
+
expect(Ssh.communicator_for('test_node', 'test_os', 'host' => 'test.host.name', 'foo' => 'bar')).to eq('ssh communicator')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/communication_adapters/vagrant'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe Vagrant do
|
7
|
+
[['test_vm', 'test_os'], ['test_node', 'test_os', {'vm_name' => 'test_vm'}]].each do |args|
|
8
|
+
describe "#communicator_for" do
|
9
|
+
let(:cmd_status) { double('status') }
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
expect(Open3).to receive(:capture2e).with('vagrant --machine-readable ssh-config test_vm').and_return([cmd_output, cmd_status])
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'vm not running' do
|
16
|
+
let(:cmd_output) {
|
17
|
+
'1402310908,,error-exit,Vagrant::Errors::SSHNotReady,The provider...'
|
18
|
+
}
|
19
|
+
|
20
|
+
it 'raises an error' do
|
21
|
+
allow(cmd_status).to receive(:success?).and_return(false)
|
22
|
+
|
23
|
+
expect {Vagrant.communicator_for(*args)}.to raise_error 'Vagrant::Errors::SSHNotReady,The provider...'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'vm running' do
|
28
|
+
let(:cmd_output) {
|
29
|
+
<<-EOS
|
30
|
+
Host test_vm
|
31
|
+
HostName test.host.name
|
32
|
+
User testuser
|
33
|
+
Port 1234
|
34
|
+
UserKnownHostsFile /dev/null
|
35
|
+
StrictHostKeyChecking no
|
36
|
+
PasswordAuthentication no
|
37
|
+
IdentityFile /test/path/private_key
|
38
|
+
IdentitiesOnly yes
|
39
|
+
LogLevel FATAL
|
40
|
+
EOS
|
41
|
+
}
|
42
|
+
|
43
|
+
include_context 'new_ssh_communicator', 'test.host.name', 'test_os', {
|
44
|
+
'user' => 'testuser',
|
45
|
+
'port' => 1234,
|
46
|
+
'keys' => '/test/path/private_key'
|
47
|
+
} do
|
48
|
+
before do
|
49
|
+
allow(cmd_status).to receive(:success?).and_return(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns and ssh communicator initialized from the vagrant command output' do
|
53
|
+
expect(Vagrant.communicator_for(*args)).to eq('ssh communicator')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'winrm'
|
2
|
+
require 'nodespec/communication_adapters/winrm_communicator'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe WinrmCommunicator do
|
7
|
+
let(:rspec_configuration) {double('rspec configuration')}
|
8
|
+
shared_examples 'creating new session' do |hostname, port, transport, options|
|
9
|
+
before do
|
10
|
+
allow(WinRM::WinRMWebService).to receive(:new).with("http://#{hostname}:#{port}/wsman", transport, options).and_return('new session')
|
11
|
+
expect(rspec_configuration).to receive(:winrm=).with('new session')
|
12
|
+
expect(rspec_configuration).to receive(:host=).with(hostname)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'creates and holds a new session' do
|
16
|
+
subject.bind_to(rspec_configuration)
|
17
|
+
|
18
|
+
expect(subject.session).to eq('new session')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'connecting to the web service' do
|
23
|
+
before do
|
24
|
+
allow(rspec_configuration).to receive(:ssh)
|
25
|
+
allow(rspec_configuration).to receive(:winrm).and_return(nil)
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'default port and transport' do
|
29
|
+
let(:subject) {WinrmCommunicator.new('test.host.name', nil, 'foo' => 'bar')}
|
30
|
+
include_examples 'creating new session', 'test.host.name', 5985, :plaintext, {foo: 'bar', disable_sspi: true}
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'custom port and transport' do
|
34
|
+
let(:subject) {WinrmCommunicator.new('test.host.name', nil, 'port' => 1234, 'transport' => 'test_transport', 'foo' => 'bar')}
|
35
|
+
include_examples 'creating new session', 'test.host.name', 1234, :test_transport, {foo: 'bar'}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'binding to configuration' do
|
40
|
+
let(:winrm_session) {double('winrm session')}
|
41
|
+
let(:subject) { WinrmCommunicator.new(
|
42
|
+
'test.host.name', nil, 'port' => 1234, 'transport' => 'test_transport', foo: 'bar', 'baz' => 'quaz')
|
43
|
+
}
|
44
|
+
|
45
|
+
before do
|
46
|
+
allow(rspec_configuration).to receive(:ssh)
|
47
|
+
end
|
48
|
+
|
49
|
+
shared_context 'existing session' do |endpoint|
|
50
|
+
before do
|
51
|
+
allow(rspec_configuration).to receive(:winrm).and_return(winrm_session)
|
52
|
+
allow(winrm_session).to receive(:endpoint).and_return(endpoint)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'existing ssh session' do
|
57
|
+
let(:ssh_session) {double('ssh session')}
|
58
|
+
before do
|
59
|
+
allow(rspec_configuration).to receive(:ssh).and_return(ssh_session)
|
60
|
+
allow(rspec_configuration).to receive(:winrm).and_return(nil)
|
61
|
+
allow(ssh_session).to receive(:host)
|
62
|
+
allow(ssh_session).to receive(:options).and_return({})
|
63
|
+
expect(ssh_session).to receive(:close)
|
64
|
+
expect(rspec_configuration).to receive(:ssh=).with(nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
include_examples 'creating new session', 'test.host.name', 1234, :test_transport, {foo: 'bar', baz: 'quaz'}
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'no existing session' do
|
71
|
+
before do
|
72
|
+
allow(rspec_configuration).to receive(:winrm).and_return(nil)
|
73
|
+
end
|
74
|
+
|
75
|
+
include_examples 'creating new session', 'test.host.name', 1234, :test_transport, {foo: 'bar', baz: 'quaz'}
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'existing session with different endpoint' do
|
79
|
+
include_context 'existing session', 'http://test.another.host.name:1234/wsman'
|
80
|
+
include_examples 'creating new session', 'test.host.name', 1234, :test_transport, {foo: 'bar', baz: 'quaz'}
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'existing session with same connection' do
|
84
|
+
include_context 'existing session', "http://test.host.name:1234/wsman"
|
85
|
+
|
86
|
+
it 'does not change the current rspec configuration' do
|
87
|
+
expect(WinRM::WinRMWebService).not_to receive(:new)
|
88
|
+
expect(rspec_configuration).not_to receive(:winrm=)
|
89
|
+
expect(rspec_configuration).not_to receive(:host=)
|
90
|
+
|
91
|
+
subject.bind_to(rspec_configuration)
|
92
|
+
|
93
|
+
expect(subject.session).to eq(winrm_session)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'provides a remote backend' do
|
99
|
+
expect(WinrmCommunicator.new('test.host.name')).to be_a(RemoteBackend)
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#initialize' do
|
103
|
+
[nil, 'Test OS'].each do |os|
|
104
|
+
it 'holds the os information' do
|
105
|
+
expect(WinrmCommunicator.new('test.host.name', os, {}).os).to eq os
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/communication_adapters/winrm'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
module CommunicationAdapters
|
6
|
+
describe Winrm do
|
7
|
+
include_context 'new_winrm_communicator', 'test.host.name', 'test_os', {'foo' => 'bar'}
|
8
|
+
|
9
|
+
it 'returns communicator with the host name from the node name' do
|
10
|
+
expect(Winrm.communicator_for('test.host.name', 'test_os', 'foo' => 'bar')).to eq('winrm communicator')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns communicator with the host name from the options' do
|
14
|
+
expect(Winrm.communicator_for('test_node', 'test_os', 'host' => 'test.host.name', 'foo' => 'bar')).to eq('winrm communicator')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'nodespec/communication_adapters'
|
2
|
+
%w[vagrant ssh aws_ec2 winrm].each {|f| require "nodespec/communication_adapters/#{f}"}
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
describe CommunicationAdapters do
|
6
|
+
{
|
7
|
+
'vagrant' => CommunicationAdapters::Vagrant,
|
8
|
+
'ssh' => CommunicationAdapters::Ssh,
|
9
|
+
'aws_ec2' => CommunicationAdapters::AwsEc2,
|
10
|
+
'winrm' => CommunicationAdapters::Winrm
|
11
|
+
}.each do |adapter_name, adapter_class|
|
12
|
+
it "retrieves a communicator from #{adapter_class}" do
|
13
|
+
expect(adapter_class).to receive(:communicator_for).with('test_node', 'test_os', 'adapter_options' => 'test_options').and_return('communicator')
|
14
|
+
|
15
|
+
communicator = CommunicationAdapters.get_communicator('test_node', 'test_os', adapter_name, 'adapter_options' => 'test_options')
|
16
|
+
|
17
|
+
expect(communicator).to eq('communicator')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'defaults to a NativeCommunicator' do
|
22
|
+
expect(CommunicationAdapters::NativeCommunicator).to receive(:new).with('test_os').and_return('communicator')
|
23
|
+
|
24
|
+
communicator = CommunicationAdapters.get_communicator('test_node', 'test_os', nil)
|
25
|
+
|
26
|
+
expect(communicator).to eq('communicator')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'nodespec/local_command_runner'
|
3
|
+
|
4
|
+
module NodeSpec
|
5
|
+
describe LocalCommandRunner do
|
6
|
+
let(:subject) {Object.new.extend LocalCommandRunner}
|
7
|
+
let(:cmd_status) { double('status') }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Open3).to receive(:capture2e).with('test command').and_return(['test output', cmd_status])
|
11
|
+
allow(subject).to receive(:execute_within_timeout).with('test command').and_yield
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns true if the command succeeds' do
|
15
|
+
allow(cmd_status).to receive(:success?).and_return(true)
|
16
|
+
|
17
|
+
expect(subject.run_command('test command')).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns false if the command fails' do
|
21
|
+
allow(cmd_status).to receive(:success?).and_return(false)
|
22
|
+
|
23
|
+
expect(subject.run_command('test command')).to be_falsy
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|