nodespec 0.1.9 → 0.1.10
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.
- 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
|