train 1.5.11 → 1.6.3
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/lib/train/transports/winrm.rb +16 -4
- data/lib/train/version.rb +1 -1
- metadata +3 -165
- data/.rubocop.yml +0 -77
- data/CHANGELOG.md +0 -900
- data/Gemfile +0 -41
- data/README.md +0 -212
- data/Rakefile +0 -73
- data/test/fixtures/plugins/train-test-fixture/LICENSE +0 -201
- data/test/fixtures/plugins/train-test-fixture/README.md +0 -5
- data/test/fixtures/plugins/train-test-fixture/lib/train-test-fixture/connection.rb +0 -35
- data/test/fixtures/plugins/train-test-fixture/lib/train-test-fixture/platform.rb +0 -18
- data/test/fixtures/plugins/train-test-fixture/lib/train-test-fixture/transport.rb +0 -14
- data/test/fixtures/plugins/train-test-fixture/lib/train-test-fixture/version.rb +0 -5
- data/test/fixtures/plugins/train-test-fixture/lib/train-test-fixture.rb +0 -4
- data/test/fixtures/plugins/train-test-fixture/pkg/train-test-fixture-0.1.0.gem +0 -0
- data/test/fixtures/plugins/train-test-fixture/train-test-fixture.gemspec +0 -35
- data/test/integration/.kitchen.yml +0 -43
- data/test/integration/Berksfile +0 -3
- data/test/integration/bootstrap.sh +0 -22
- data/test/integration/chefignore +0 -1
- data/test/integration/cookbooks/test/metadata.rb +0 -1
- data/test/integration/cookbooks/test/recipes/default.rb +0 -100
- data/test/integration/cookbooks/test/recipes/prep_files.rb +0 -56
- data/test/integration/docker_run.rb +0 -153
- data/test/integration/docker_test.rb +0 -24
- data/test/integration/docker_test_container.rb +0 -24
- data/test/integration/helper.rb +0 -61
- data/test/integration/sudo/customcommand.rb +0 -15
- data/test/integration/sudo/nopasswd.rb +0 -16
- data/test/integration/sudo/passwd.rb +0 -21
- data/test/integration/sudo/reqtty.rb +0 -17
- data/test/integration/sudo/run_as.rb +0 -12
- data/test/integration/test-travis-centos.yml +0 -6
- data/test/integration/test-travis-debian.yml +0 -6
- data/test/integration/test-travis-fedora.yml +0 -8
- data/test/integration/test-travis-oel.yml +0 -6
- data/test/integration/test-travis-ubuntu.yml +0 -8
- data/test/integration/test_local.rb +0 -19
- data/test/integration/test_ssh.rb +0 -39
- data/test/integration/tests/path_block_device_test.rb +0 -74
- data/test/integration/tests/path_character_device_test.rb +0 -74
- data/test/integration/tests/path_file_test.rb +0 -99
- data/test/integration/tests/path_folder_test.rb +0 -90
- data/test/integration/tests/path_missing_test.rb +0 -76
- data/test/integration/tests/path_pipe_test.rb +0 -62
- data/test/integration/tests/path_symlink_test.rb +0 -95
- data/test/integration/tests/run_command_test.rb +0 -35
- data/test/unit/extras/command_wrapper_test.rb +0 -110
- data/test/unit/extras/stat_test.rb +0 -210
- data/test/unit/file/local/unix_test.rb +0 -224
- data/test/unit/file/local/windows_test.rb +0 -101
- data/test/unit/file/local_test.rb +0 -121
- data/test/unit/file/remote/aix_test.rb +0 -81
- data/test/unit/file/remote/linux_test.rb +0 -221
- data/test/unit/file/remote/qnx_test.rb +0 -80
- data/test/unit/file/remote/unix_test.rb +0 -119
- data/test/unit/file/remote/windows_test.rb +0 -72
- data/test/unit/file/remote_test.rb +0 -62
- data/test/unit/file_test.rb +0 -129
- data/test/unit/helper.rb +0 -7
- data/test/unit/platforms/detect/os_common_test.rb +0 -85
- data/test/unit/platforms/detect/os_linux_test.rb +0 -132
- data/test/unit/platforms/detect/os_windows_test.rb +0 -107
- data/test/unit/platforms/detect/scanner_test.rb +0 -61
- data/test/unit/platforms/detect/uuid_test.rb +0 -133
- data/test/unit/platforms/family_test.rb +0 -32
- data/test/unit/platforms/os_detect_test.rb +0 -249
- data/test/unit/platforms/platform_test.rb +0 -405
- data/test/unit/platforms/platforms_test.rb +0 -52
- data/test/unit/plugins/connection_test.rb +0 -219
- data/test/unit/plugins/transport_test.rb +0 -111
- data/test/unit/plugins_test.rb +0 -22
- data/test/unit/train_test.rb +0 -247
- data/test/unit/transports/aws_test.rb +0 -120
- data/test/unit/transports/azure_test.rb +0 -145
- data/test/unit/transports/cisco_ios_connection.rb +0 -92
- data/test/unit/transports/gcp_test.rb +0 -266
- data/test/unit/transports/helpers/azure/file_credentials_test.rb +0 -129
- data/test/unit/transports/local_test.rb +0 -183
- data/test/unit/transports/mock_test.rb +0 -150
- data/test/unit/transports/ssh_test.rb +0 -330
- data/test/unit/transports/vmware_test.rb +0 -159
- data/test/unit/version_test.rb +0 -8
- data/test/windows/local_test.rb +0 -243
- data/test/windows/winrm_test.rb +0 -187
- data/train.gemspec +0 -45
@@ -1,150 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'helper'
|
3
|
-
require 'train/transports/mock'
|
4
|
-
require 'digest/sha2'
|
5
|
-
|
6
|
-
describe 'mock transport' do
|
7
|
-
let(:transport) { Train::Transports::Mock.new(verbose: true) }
|
8
|
-
let(:connection) { transport.connection }
|
9
|
-
|
10
|
-
it 'can be instantiated' do
|
11
|
-
transport.wont_be_nil
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'can create a connection' do
|
15
|
-
connection.wont_be_nil
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'provides a uri' do
|
19
|
-
connection.uri.must_equal 'mock://'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'provides a run_command_via_connection method' do
|
23
|
-
methods = connection.class.private_instance_methods(false)
|
24
|
-
methods.include?(:run_command_via_connection).must_equal true
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'provides a file_via_connection method' do
|
28
|
-
methods = connection.class.private_instance_methods(false)
|
29
|
-
methods.include?(:file_via_connection).must_equal true
|
30
|
-
end
|
31
|
-
|
32
|
-
describe 'when running a mocked command' do
|
33
|
-
let(:mock_cmd) { }
|
34
|
-
|
35
|
-
it 'has a simple mock command creator' do
|
36
|
-
out = rand
|
37
|
-
cls = Train::Transports::Mock::Connection::Command
|
38
|
-
res = cls.new(out, '', 0)
|
39
|
-
connection.mock_command('test', out).must_equal res
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'handles nil commands' do
|
43
|
-
connection.run_command(nil).stdout.must_equal('')
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'can mock up nil commands' do
|
47
|
-
out = rand
|
48
|
-
connection.mock_command('', rand) # don't pull this result! always mock the input
|
49
|
-
connection.mock_command(nil, out) # pull this result
|
50
|
-
connection.run_command(nil).stdout.must_equal(out)
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'gets results for stdout' do
|
54
|
-
out = rand
|
55
|
-
cmd = rand
|
56
|
-
connection.mock_command(cmd, out)
|
57
|
-
connection.run_command(cmd).stdout.must_equal(out)
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'gets results for stderr' do
|
61
|
-
err = rand
|
62
|
-
cmd = rand
|
63
|
-
connection.mock_command(cmd, nil, err)
|
64
|
-
connection.run_command(cmd).stderr.must_equal(err)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'gets results for exit_status' do
|
68
|
-
code = rand
|
69
|
-
cmd = rand
|
70
|
-
connection.mock_command(cmd, nil, nil, code)
|
71
|
-
connection.run_command(cmd).exit_status.must_equal(code)
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'can mock a command via its SHA2 sum' do
|
75
|
-
out = rand.to_s
|
76
|
-
cmd = rand.to_s
|
77
|
-
shacmd = Digest::SHA256.hexdigest cmd
|
78
|
-
connection.mock_command(shacmd, out)
|
79
|
-
connection.run_command(cmd).stdout.must_equal(out)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
describe 'when accessing a mocked os' do
|
84
|
-
it 'has the default mock os faily set to mock' do
|
85
|
-
connection.os[:name].must_equal 'mock'
|
86
|
-
connection.platform[:name].must_equal 'mock'
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'sets the OS to the mocked value' do
|
90
|
-
connection.mock_os({ name: 'centos', family: 'redhat' })
|
91
|
-
connection.os.linux?.must_equal true
|
92
|
-
connection.os.redhat?.must_equal true
|
93
|
-
connection.os[:family].must_equal 'redhat'
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'allows the setting of the name' do
|
97
|
-
connection.mock_os({ name: 'foo' })
|
98
|
-
connection.os[:name].must_equal 'foo'
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'allows setting of the family' do
|
102
|
-
connection.mock_os({ family: 'foo' })
|
103
|
-
connection.os[:family].must_equal 'foo'
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'allows setting of the release' do
|
107
|
-
connection.mock_os({ release: '1.2.3' })
|
108
|
-
connection.os[:release].must_equal '1.2.3'
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'allows setting of the arch' do
|
112
|
-
connection.mock_os({ arch: 'amd123' })
|
113
|
-
connection.os[:arch].must_equal 'amd123'
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'allow setting of multiple values' do
|
117
|
-
connection.mock_os({ name: 'foo', family: 'bar' })
|
118
|
-
connection.os[:name].must_equal 'foo'
|
119
|
-
connection.os[:family].must_equal 'bar'
|
120
|
-
connection.os[:arch].must_equal 'unknown'
|
121
|
-
connection.os[:release].must_equal 'unknown'
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'properly handles a nil value' do
|
125
|
-
connection.mock_os(nil)
|
126
|
-
connection.os[:name].must_equal 'mock'
|
127
|
-
connection.os[:family].must_equal 'mock'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe 'when accessing a mocked file' do
|
132
|
-
it 'handles a non-existing file' do
|
133
|
-
x = rand.to_s
|
134
|
-
f = connection.file(x)
|
135
|
-
f.must_be_kind_of Train::Transports::Mock::Connection::File
|
136
|
-
f.exist?.must_equal false
|
137
|
-
f.path.must_equal x
|
138
|
-
end
|
139
|
-
|
140
|
-
# tests if all fields between the local json and resulting mock file
|
141
|
-
# are equal
|
142
|
-
JSON_DATA = Train.create('local').connection.file(__FILE__).to_json
|
143
|
-
RES = Train::Transports::Mock::Connection::File.from_json(JSON_DATA)
|
144
|
-
%w{ content mode owner group }.each do |f|
|
145
|
-
it "can be initialized from json (field #{f})" do
|
146
|
-
RES.method(f).call.must_equal JSON_DATA[f]
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
@@ -1,330 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'helper'
|
4
|
-
require 'train/transports/ssh'
|
5
|
-
|
6
|
-
describe 'ssh transport' do
|
7
|
-
let(:cls) do
|
8
|
-
plat = Train::Platforms.name('mock').in_family('linux')
|
9
|
-
plat.add_platform_methods
|
10
|
-
Train::Platforms::Detect.stubs(:scan).returns(plat)
|
11
|
-
Train::Transports::SSH
|
12
|
-
end
|
13
|
-
let(:conf) {{
|
14
|
-
host: rand.to_s,
|
15
|
-
password: rand.to_s,
|
16
|
-
key_files: rand.to_s,
|
17
|
-
proxy_command: 'ssh root@127.0.0.1 -W %h:%p',
|
18
|
-
}}
|
19
|
-
let(:cls_agent) { cls.new({ host: rand.to_s }) }
|
20
|
-
|
21
|
-
describe 'default options' do
|
22
|
-
let(:ssh) { cls.new({ host: 'dummy' }) }
|
23
|
-
|
24
|
-
it 'can be instantiated (with valid config)' do
|
25
|
-
ssh.wont_be_nil
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'configures the host' do
|
29
|
-
ssh.options[:host].must_equal 'dummy'
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'has default port' do
|
33
|
-
ssh.options[:port].must_equal 22
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'has default user' do
|
37
|
-
ssh.options[:user].must_equal 'root'
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'by default does not request a pty' do
|
41
|
-
ssh.options[:pty].must_equal false
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe 'connection options' do
|
46
|
-
let(:ssh) { cls.new({ host: 'dummy' }) }
|
47
|
-
let(:connection_options) { ssh.send(:connection_options, {}) }
|
48
|
-
|
49
|
-
it 'does not set a paranoid option - deprecated in net-ssh 4.2' do
|
50
|
-
connection_options.key?(:paranoid).must_equal false
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'sets a verify_host_key option, replacement for paranoid' do
|
54
|
-
connection_options[:verify_host_key].must_equal false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe 'ssh options' do
|
59
|
-
let(:ssh) { cls.new(conf) }
|
60
|
-
let(:connection) { ssh.connection }
|
61
|
-
it 'includes BatchMode when :non_interactive is set' do
|
62
|
-
conf[:non_interactive] = true
|
63
|
-
connection.ssh_opts.include?("BatchMode=yes").must_equal true
|
64
|
-
end
|
65
|
-
it 'excludes BatchMode when :non_interactive is not set' do
|
66
|
-
connection.ssh_opts.include?("BatchMode=yes").must_equal false
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'opening a connection' do
|
71
|
-
let(:ssh) { cls.new(conf) }
|
72
|
-
let(:connection) { ssh.connection }
|
73
|
-
|
74
|
-
it 'provides a run_command_via_connection method' do
|
75
|
-
methods = connection.class.private_instance_methods(false)
|
76
|
-
methods.include?(:run_command_via_connection).must_equal true
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'provides a file_via_connection method' do
|
80
|
-
methods = connection.class.private_instance_methods(false)
|
81
|
-
methods.include?(:file_via_connection).must_equal true
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'gets the connection' do
|
85
|
-
connection.must_be_kind_of Train::Transports::SSH::Connection
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'provides a uri' do
|
89
|
-
connection.uri.must_equal "ssh://root@#{conf[:host]}:22"
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'must respond to wait_until_ready' do
|
93
|
-
connection.must_respond_to :wait_until_ready
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'can be closed' do
|
97
|
-
connection.close.must_be_nil
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'has a login command == ssh' do
|
101
|
-
connection.login_command.command.must_equal 'ssh'
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'has login command arguments' do
|
105
|
-
connection.login_command.arguments.must_equal([
|
106
|
-
"-o", "UserKnownHostsFile=/dev/null",
|
107
|
-
"-o", "StrictHostKeyChecking=no",
|
108
|
-
"-o", "IdentitiesOnly=yes",
|
109
|
-
"-o", "LogLevel=VERBOSE",
|
110
|
-
"-o", "ForwardAgent=no",
|
111
|
-
"-i", conf[:key_files],
|
112
|
-
"-o", "ProxyCommand='ssh root@127.0.0.1 -W %h:%p'",
|
113
|
-
"-p", "22",
|
114
|
-
"root@#{conf[:host]}",
|
115
|
-
])
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'sets the right auth_methods when password is specified' do
|
119
|
-
conf[:key_files] = nil
|
120
|
-
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "password", "keyboard-interactive"]
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'sets the right auth_methods when keys are specified' do
|
124
|
-
conf[:password] = nil
|
125
|
-
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "publickey"]
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'sets the right auth_methods for agent auth' do
|
129
|
-
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
|
130
|
-
cls_agent.connection.method(:options).call[:auth_methods].must_equal ['none', 'publickey']
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'works with ssh agent auth' do
|
134
|
-
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
|
135
|
-
cls_agent.connection
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'sets up a proxy when ssh proxy command is specified' do
|
139
|
-
mock = MiniTest::Mock.new
|
140
|
-
mock.expect(:call, true) do |hostname, username, options|
|
141
|
-
options[:proxy].kind_of?(Net::SSH::Proxy::Command) &&
|
142
|
-
'ssh root@127.0.0.1 -W %h:%p' == options[:proxy].command_line_template
|
143
|
-
end
|
144
|
-
connection.stubs(:run_command)
|
145
|
-
Net::SSH.stub(:start, mock) do
|
146
|
-
connection.wait_until_ready
|
147
|
-
end
|
148
|
-
mock.verify
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe 'converting connection to string for logging' do
|
153
|
-
it 'masks passwords' do
|
154
|
-
assert_output(/.*:password=>"<hidden>".*/) do
|
155
|
-
connection = cls.new(conf).connection
|
156
|
-
puts "#{connection}"
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
describe 'failed configuration' do
|
162
|
-
it 'works with a minimum valid config' do
|
163
|
-
cls.new(conf).connection
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'does not like host == nil' do
|
167
|
-
conf.delete(:host)
|
168
|
-
proc { cls.new(conf).connection }.must_raise Train::ClientError
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'reverts to root on user == nil' do
|
172
|
-
conf[:user] = nil
|
173
|
-
cls.new(conf).connection.method(:options).call[:user] == 'root'
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'does not like key and password == nil' do
|
177
|
-
cls_agent.stubs(:ssh_known_identities).returns({})
|
178
|
-
proc { cls_agent.connection }.must_raise Train::ClientError
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'wont connect if it is not possible' do
|
182
|
-
conf[:host] = 'localhost'
|
183
|
-
conf[:port] = 1
|
184
|
-
conf.delete :proxy_command
|
185
|
-
conn = cls.new(conf).connection
|
186
|
-
proc { conn.run_command('uname') }.must_raise Train::Transports::SSHFailed
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
describe 'ssh transport with bastion' do
|
192
|
-
let(:cls) do
|
193
|
-
plat = Train::Platforms.name('mock').in_family('linux')
|
194
|
-
plat.add_platform_methods
|
195
|
-
Train::Platforms::Detect.stubs(:scan).returns(plat)
|
196
|
-
Train::Transports::SSH
|
197
|
-
end
|
198
|
-
|
199
|
-
let(:conf) {{
|
200
|
-
host: rand.to_s,
|
201
|
-
password: rand.to_s,
|
202
|
-
key_files: rand.to_s,
|
203
|
-
bastion_host: 'bastion_dummy',
|
204
|
-
}}
|
205
|
-
let(:cls_agent) { cls.new({ host: rand.to_s }) }
|
206
|
-
|
207
|
-
describe 'bastion' do
|
208
|
-
describe 'default options' do
|
209
|
-
let(:ssh) { cls.new({ bastion_host: 'bastion_dummy' }) }
|
210
|
-
|
211
|
-
it 'configures the host' do
|
212
|
-
ssh.options[:bastion_host].must_equal 'bastion_dummy'
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'has default port' do
|
216
|
-
ssh.options[:bastion_port].must_equal 22
|
217
|
-
end
|
218
|
-
|
219
|
-
it 'has default user' do
|
220
|
-
ssh.options[:bastion_user].must_equal 'root'
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe 'opening a connection' do
|
225
|
-
let(:ssh) { cls.new(conf) }
|
226
|
-
let(:connection) { ssh.connection }
|
227
|
-
|
228
|
-
it 'provides a run_command_via_connection method' do
|
229
|
-
methods = connection.class.private_instance_methods(false)
|
230
|
-
methods.include?(:run_command_via_connection).must_equal true
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'provides a file_via_connection method' do
|
234
|
-
methods = connection.class.private_instance_methods(false)
|
235
|
-
methods.include?(:file_via_connection).must_equal true
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'gets the connection' do
|
239
|
-
connection.must_be_kind_of Train::Transports::SSH::Connection
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'provides a uri' do
|
243
|
-
connection.uri.must_equal "ssh://root@#{conf[:host]}:22"
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'must respond to wait_until_ready' do
|
247
|
-
connection.must_respond_to :wait_until_ready
|
248
|
-
end
|
249
|
-
|
250
|
-
it 'can be closed' do
|
251
|
-
connection.close.must_be_nil
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'has a login command == ssh' do
|
255
|
-
connection.login_command.command.must_equal 'ssh'
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'has login command arguments' do
|
259
|
-
connection.login_command.arguments.must_equal([
|
260
|
-
"-o", "UserKnownHostsFile=/dev/null",
|
261
|
-
"-o", "StrictHostKeyChecking=no",
|
262
|
-
"-o", "IdentitiesOnly=yes",
|
263
|
-
"-o", "LogLevel=VERBOSE",
|
264
|
-
"-o", "ForwardAgent=no",
|
265
|
-
"-i", conf[:key_files],
|
266
|
-
"-o", "ProxyCommand='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -o LogLevel=VERBOSE -o ForwardAgent=no -i #{conf[:key_files]} root@bastion_dummy -p 22 -W %h:%p'",
|
267
|
-
"-p", "22",
|
268
|
-
"root@#{conf[:host]}",
|
269
|
-
])
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'sets the right auth_methods when password is specified' do
|
273
|
-
conf[:key_files] = nil
|
274
|
-
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "password", "keyboard-interactive"]
|
275
|
-
end
|
276
|
-
|
277
|
-
it 'sets the right auth_methods when keys are specified' do
|
278
|
-
conf[:password] = nil
|
279
|
-
cls.new(conf).connection.method(:options).call[:auth_methods].must_equal ["none", "publickey"]
|
280
|
-
end
|
281
|
-
|
282
|
-
it 'sets the right auth_methods for agent auth' do
|
283
|
-
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
|
284
|
-
cls_agent.connection.method(:options).call[:auth_methods].must_equal ['none', 'publickey']
|
285
|
-
end
|
286
|
-
|
287
|
-
it 'works with ssh agent auth' do
|
288
|
-
cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
|
289
|
-
cls_agent.connection
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'sets up a proxy when ssh proxy command is specified' do
|
293
|
-
mock = MiniTest::Mock.new
|
294
|
-
mock.expect(:call, true) do |hostname, username, options|
|
295
|
-
options[:proxy].kind_of?(Net::SSH::Proxy::Command) &&
|
296
|
-
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -o LogLevel=VERBOSE -o ForwardAgent=no -i #{conf[:key_files]} root@bastion_dummy -p 22 -W %h:%p" == options[:proxy].command_line_template
|
297
|
-
end
|
298
|
-
connection.stubs(:run_command)
|
299
|
-
Net::SSH.stub(:start, mock) do
|
300
|
-
connection.wait_until_ready
|
301
|
-
end
|
302
|
-
mock.verify
|
303
|
-
end
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
describe 'ssh transport with bastion and proxy' do
|
309
|
-
let(:cls) do
|
310
|
-
plat = Train::Platforms.name('mock').in_family('linux')
|
311
|
-
plat.add_platform_methods
|
312
|
-
Train::Platforms::Detect.stubs(:scan).returns(plat)
|
313
|
-
Train::Transports::SSH
|
314
|
-
end
|
315
|
-
|
316
|
-
let(:conf) {{
|
317
|
-
host: rand.to_s,
|
318
|
-
password: rand.to_s,
|
319
|
-
key_files: rand.to_s,
|
320
|
-
bastion_host: 'bastion_dummy',
|
321
|
-
proxy_command: 'dummy'
|
322
|
-
}}
|
323
|
-
let(:cls_agent) { cls.new({ host: rand.to_s }) }
|
324
|
-
|
325
|
-
describe 'bastion and proxy' do
|
326
|
-
it 'will throw an exception when both proxy_command and bastion_host is specified' do
|
327
|
-
proc { cls.new(conf).connection }.must_raise Train::ClientError
|
328
|
-
end
|
329
|
-
end
|
330
|
-
end
|
@@ -1,159 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'helper'
|
3
|
-
|
4
|
-
describe 'Train::Transports::VMware::Connection' do
|
5
|
-
def add_stubs(stub_options)
|
6
|
-
Train::Transports::VMware::Connection.any_instance
|
7
|
-
.stubs(:detect_powershell_binary)
|
8
|
-
.returns(stub_options[:powershell_binary] || :pwsh)
|
9
|
-
Train::Transports::VMware::Connection.any_instance
|
10
|
-
.stubs(:powercli_version)
|
11
|
-
.returns('10.1.1.8827525')
|
12
|
-
Train::Transports::VMware::Connection.any_instance
|
13
|
-
.stubs(:run_command_via_connection)
|
14
|
-
.with('(Get-VMHost | Get-View).hardware.systeminfo.uuid')
|
15
|
-
.returns(stub_options[:mock_uuid_result] || nil)
|
16
|
-
if stub_options[:mock_connect_result]
|
17
|
-
Train::Transports::VMware::Connection.any_instance
|
18
|
-
.expects(:run_command_via_connection)
|
19
|
-
.with('Connect-VIServer 10.0.0.10 -User testuser -Password supersecurepassword | Out-Null')
|
20
|
-
.returns(stub_options[:mock_connect_result])
|
21
|
-
else
|
22
|
-
Train::Transports::VMware::Connection.any_instance
|
23
|
-
.stubs(:connect)
|
24
|
-
.returns(nil)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def create_transport(options = {})
|
29
|
-
ENV['VISERVER'] = '10.0.0.10'
|
30
|
-
ENV['VISERVER_USERNAME'] = 'testuser'
|
31
|
-
ENV['VISERVER_PASSWORD'] = 'supersecurepassword'
|
32
|
-
|
33
|
-
# Need to require this here as it captures the ENV variables on load
|
34
|
-
require 'train/transports/vmware'
|
35
|
-
add_stubs(options[:stub_options] || {})
|
36
|
-
Train::Transports::VMware.new(options[:transport_options])
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '#initialize' do
|
40
|
-
it 'defaults to ENV options' do
|
41
|
-
options = create_transport.connection.instance_variable_get(:@options)
|
42
|
-
options[:viserver].must_equal '10.0.0.10'
|
43
|
-
options[:username].must_equal 'testuser'
|
44
|
-
options[:password].must_equal 'supersecurepassword'
|
45
|
-
options[:insecure].must_equal false
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'allows for overriding options' do
|
49
|
-
transport = create_transport(
|
50
|
-
transport_options: {
|
51
|
-
viserver: '10.1.1.1',
|
52
|
-
username: 'anotheruser',
|
53
|
-
password: 'notsecurepassword',
|
54
|
-
insecure: false,
|
55
|
-
}
|
56
|
-
)
|
57
|
-
options = transport.connection.instance_variable_get(:@options)
|
58
|
-
options[:viserver].must_equal '10.1.1.1'
|
59
|
-
options[:username].must_equal 'anotheruser'
|
60
|
-
options[:password].must_equal 'notsecurepassword'
|
61
|
-
options[:insecure].must_equal false
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'ignores certificate validation if --insecure is used' do
|
65
|
-
Train::Transports::VMware::Connection.any_instance
|
66
|
-
.expects(:run_command_via_connection)
|
67
|
-
.with('Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Scope Session -Confirm:$False')
|
68
|
-
.returns(nil)
|
69
|
-
transport = create_transport(transport_options: { insecure: true })
|
70
|
-
options = transport.connection.instance_variable_get(:@options)
|
71
|
-
options[:insecure].must_equal true
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'uses the Local connection when Windows PowerShell is found' do
|
75
|
-
require 'train/transports/local'
|
76
|
-
Train::Transports::Local::Connection.expects(:new)
|
77
|
-
create_transport(
|
78
|
-
stub_options: {
|
79
|
-
powershell_binary: :powershell
|
80
|
-
}
|
81
|
-
).connection
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe '#connect' do
|
86
|
-
def mock_connect_result(stderr, exit_status)
|
87
|
-
OpenStruct.new(stderr: stderr, exit_status: exit_status)
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'raises certificate error when stderr matches regular expression' do
|
91
|
-
e = proc {
|
92
|
-
create_transport(
|
93
|
-
stub_options: {
|
94
|
-
mock_connect_result: mock_connect_result(
|
95
|
-
'Invalid server certificate', 1
|
96
|
-
)
|
97
|
-
}
|
98
|
-
).connection
|
99
|
-
}.must_raise(RuntimeError)
|
100
|
-
e.message.must_match /Unable to connect.*Please use `--insecure`/
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'raises auth error when stderr matches regular expression' do
|
104
|
-
e = proc {
|
105
|
-
create_transport(
|
106
|
-
stub_options: {
|
107
|
-
mock_connect_result: mock_connect_result(
|
108
|
-
'incorrect user name or password', 1
|
109
|
-
)
|
110
|
-
}
|
111
|
-
).connection
|
112
|
-
}.must_raise(RuntimeError)
|
113
|
-
e.message.must_match /Unable to connect.*Incorrect username/
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'redacts the password when an unspecified error is raised' do
|
117
|
-
e = proc {
|
118
|
-
create_transport(
|
119
|
-
stub_options: {
|
120
|
-
mock_connect_result: mock_connect_result(
|
121
|
-
'something unexpected -Password supersecret -AnotherOption', 1
|
122
|
-
)
|
123
|
-
}
|
124
|
-
).connection
|
125
|
-
}.must_raise(RuntimeError)
|
126
|
-
e.message.must_match /-Password REDACTED/
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe '#platform' do
|
131
|
-
it 'returns correct platform details' do
|
132
|
-
platform = create_transport.connection.platform
|
133
|
-
platform.clean_name.must_equal 'vmware'
|
134
|
-
platform.family_hierarchy.must_equal ['cloud', 'api']
|
135
|
-
platform.platform.must_equal(release: 'vmware-powercli-10.1.1.8827525')
|
136
|
-
platform.vmware?.must_equal true
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#unique_identifier' do
|
141
|
-
it 'returns the correct unique identifier' do
|
142
|
-
uuid = '1f261432-e23e-6911-841c-94c6911a02dd'
|
143
|
-
mock_uuid_result = OpenStruct.new(
|
144
|
-
stdout: uuid + "\n"
|
145
|
-
)
|
146
|
-
connection = create_transport(
|
147
|
-
stub_options: { mock_uuid_result: mock_uuid_result }
|
148
|
-
).connection
|
149
|
-
|
150
|
-
connection.unique_identifier.must_equal(uuid)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe '#uri' do
|
155
|
-
it 'returns the correct URI' do
|
156
|
-
create_transport.connection.uri.must_equal 'vmware://testuser@10.0.0.10'
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|