train 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d1f4e075a5038b0b0a9775e730adb61029aa31c
4
- data.tar.gz: e6bca8857718107fcaae0683d99e921dc38cdf7e
3
+ metadata.gz: 124fd4ed4c208f576481fb0b295fb8db93d9dd21
4
+ data.tar.gz: '0680e4d022b89b9e94abcd2f76ec830c69936ec9'
5
5
  SHA512:
6
- metadata.gz: 1ad43c36e91b4471e56d623433239db881c32ba7a266bf8de70bf7f863feaee87dc78b5628c4fa7980db451a8c220c604a97ee4346df2109d0010be1411ee115
7
- data.tar.gz: 8fde9bf9ae3281f82abd7785ba8e4886c878b152bc4fa00434a2d3271cbaccc9e86abb9262394baa66798eb9a8a6522ca0905eee4016d17abfd4400c2de0ac1a
6
+ metadata.gz: 7a82299c5aea2a11cbaf596a8aaa6bee503e7a169c86934b7af9a379ae70fc72fddbde527dcea1b717b08795d270a8092a223f72d7b582e8ded18b5c99180d56
7
+ data.tar.gz: db232796a60f74458d26ceff2273e72a233fcb14f794b03c6c9e45dfda7ba84e0632005a2c3c6df2ef9b2d7e816044f9589003cea87c890ea0e369fdc9f68838
data/CHANGELOG.md CHANGED
@@ -1,10 +1,31 @@
1
1
  # Change Log
2
2
 
3
- ## [1.1.1](https://github.com/chef/train/tree/1.1.1) (2018-02-14)
4
- [Full Changelog](https://github.com/chef/train/compare/v1.1.0...1.1.1)
3
+ ## [1.2.0](https://github.com/chef/train/tree/1.2.0) (2018-03-15)
4
+ [Full Changelog](https://github.com/chef/train/compare/v1.1.1...1.2.0)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - Change error message to use `connection` [\#263](https://github.com/chef/train/pull/263) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
9
+
10
+ **Closed issues:**
11
+
12
+ - Force 64bit powershell if using ruby32 on a 64bit os [\#265](https://github.com/chef/train/issues/265)
13
+ - Master OS detect family [\#260](https://github.com/chef/train/issues/260)
14
+
15
+ **Merged pull requests:**
16
+
17
+ - Force 64bit powershell for 32bit ruby running on 64bit windows [\#266](https://github.com/chef/train/pull/266) ([jquick](https://github.com/jquick))
18
+ - support cisco ios xe [\#262](https://github.com/chef/train/pull/262) ([arlimus](https://github.com/arlimus))
19
+ - Create a master OS family and refactor specifications [\#261](https://github.com/chef/train/pull/261) ([jquick](https://github.com/jquick))
20
+ - Support for Brocade FOS-based SAN devices [\#254](https://github.com/chef/train/pull/254) ([marcelhuth](https://github.com/marcelhuth))
21
+ - ProxyCommand support [\#227](https://github.com/chef/train/pull/227) ([cbeckr](https://github.com/cbeckr))
22
+
23
+ ## [v1.1.1](https://github.com/chef/train/tree/v1.1.1) (2018-02-14)
24
+ [Full Changelog](https://github.com/chef/train/compare/v1.1.0...v1.1.1)
5
25
 
6
26
  **Merged pull requests:**
7
27
 
28
+ - Release train 1.1.1 [\#259](https://github.com/chef/train/pull/259) ([jquick](https://github.com/jquick))
8
29
  - Add api sdk versions as platform release [\#258](https://github.com/chef/train/pull/258) ([jquick](https://github.com/jquick))
9
30
  - Add plat helper methods to api direct platforms. [\#257](https://github.com/chef/train/pull/257) ([jquick](https://github.com/jquick))
10
31
 
@@ -53,6 +53,18 @@ module Train::Platforms::Detect::Helpers
53
53
  @uname[:m] = command_output('uname -m')
54
54
  end
55
55
 
56
+ def brocade_version
57
+ return @cache[:brocade] if @cache.key?(:brocade)
58
+ res = command_output('version')
59
+
60
+ m = res.match(/^Fabric OS:\s+v(\S+)$/)
61
+ unless m.nil?
62
+ return @cache[:brocade] = { version: m[1], type: 'fos' }
63
+ end
64
+
65
+ @cache[:brocade] = nil
66
+ end
67
+
56
68
  def cisco_show_version
57
69
  return @cache[:cisco] if @cache.key?(:cisco)
58
70
  res = command_output('show version')
@@ -62,6 +74,11 @@ module Train::Platforms::Detect::Helpers
62
74
  return @cache[:cisco] = { version: m[2], model: m[1], type: 'ios' }
63
75
  end
64
76
 
77
+ m = res.match(/^Cisco IOS Software, IOS-XE Software, [^,]+? \(([^,]+?)\), Version (\d+\.\d+\.\d+[A-Z]*)/)
78
+ unless m.nil?
79
+ return @cache[:cisco] = { version: m[2], model: m[1], type: 'ios-xe' }
80
+ end
81
+
65
82
  m = res.match(/^Cisco Nexus Operating System \(NX-OS\) Software/)
66
83
  unless m.nil?
67
84
  v = res[/^\s*system:\s+version (\d+\.\d+)/, 1]
@@ -12,7 +12,10 @@ module Train::Platforms::Detect::Specifications
12
12
  def self.load
13
13
  plat = Train::Platforms
14
14
 
15
- plat.family('windows')
15
+ # master family
16
+ plat.family('os').detect { true }
17
+
18
+ plat.family('windows').in_family('os')
16
19
  .detect {
17
20
  if winrm? || (@backend.local? && ruby_host_os(/mswin|mingw32|windows/))
18
21
  true
@@ -25,81 +28,16 @@ module Train::Platforms::Detect::Specifications
25
28
  }
26
29
 
27
30
  # unix master family
28
- plat.family('unix')
31
+ plat.family('unix').in_family('os')
29
32
  .detect {
30
33
  # we want to catch a special case here where cisco commands
31
34
  # don't return an exit status and still print to stdout
32
- if unix_uname_s =~ /./ && !unix_uname_s.start_with?('Line has invalid autocommand ')
35
+ if unix_uname_s =~ /./ && !unix_uname_s.start_with?('Line has invalid autocommand ') && !unix_uname_s.start_with?('The command you have entered')
33
36
  @platform[:arch] = unix_uname_m
34
37
  true
35
38
  end
36
39
  }
37
40
 
38
- # cisco_ios family
39
- plat.family('cisco').title('Cisco Family')
40
- .detect {
41
- !cisco_show_version.nil?
42
- }
43
-
44
- plat.name('cisco_ios').title('Cisco IOS').in_family('cisco')
45
- .detect {
46
- v = cisco_show_version
47
- next unless v[:type] == 'ios'
48
- @platform[:release] = v[:version]
49
- @platform[:arch] = nil
50
- true
51
- }
52
-
53
- plat.name('cisco_nexus').title('Cisco Nexus').in_family('cisco')
54
- .detect {
55
- v = cisco_show_version
56
- next unless v[:type] == 'nexus'
57
- @platform[:release] = v[:version]
58
- @platform[:arch] = nil
59
- true
60
- }
61
-
62
- # arista_eos family
63
- # this has to be before redhat as EOS is based off fedora
64
- plat.family('arista_eos').title('Arista EOS Family').in_family('unix')
65
- .detect {
66
- # we need a better way to determin this family
67
- # for now we are going to just try each platform
68
- true
69
- }
70
- plat.name('arista_eos').title('Arista EOS').in_family('arista_eos')
71
- .detect {
72
- cmd = @backend.run_command('show version | json')
73
- if cmd.exit_status == 0 && !cmd.stdout.empty?
74
- require 'json'
75
- begin
76
- eos_ver = JSON.parse(cmd.stdout)
77
- @platform[:release] = eos_ver['version']
78
- @platform[:arch] = eos_ver['architecture']
79
- true
80
- rescue JSON::ParserError
81
- nil
82
- end
83
- end
84
- }
85
- plat.name('arista_eos_bash').title('Arista EOS Bash Shell').in_family('arista_eos')
86
- .detect {
87
- if unix_file_exist?('/usr/bin/FastCli')
88
- cmd = @backend.run_command('FastCli -p 15 -c "show version | json"')
89
- if cmd.exit_status == 0 && !cmd.stdout.empty?
90
- require 'json'
91
- begin
92
- eos_ver = JSON.parse(cmd.stdout)
93
- @platform[:release] = eos_ver['version']
94
- @platform[:arch] = eos_ver['architecture']
95
- true
96
- rescue JSON::ParserError
97
- nil
98
- end
99
- end
100
- end
101
- }
102
-
103
41
  # linux master family
104
42
  plat.family('linux').in_family('unix')
105
43
  .detect {
@@ -159,6 +97,31 @@ module Train::Platforms::Detect::Specifications
159
97
  true
160
98
  }
161
99
 
100
+ # arista_eos family
101
+ # this checks for the arista bash shell
102
+ # must come before redhat as it uses fedora under the hood
103
+ plat.family('arista_eos').title('Arista EOS Family').in_family('linux')
104
+ .detect {
105
+ true
106
+ }
107
+ plat.name('arista_eos_bash').title('Arista EOS Bash Shell').in_family('arista_eos')
108
+ .detect {
109
+ if unix_file_exist?('/usr/bin/FastCli')
110
+ cmd = @backend.run_command('FastCli -p 15 -c "show version | json"')
111
+ if cmd.exit_status == 0 && !cmd.stdout.empty?
112
+ require 'json'
113
+ begin
114
+ eos_ver = JSON.parse(cmd.stdout)
115
+ @platform[:release] = eos_ver['version']
116
+ @platform[:arch] = eos_ver['architecture']
117
+ true
118
+ rescue JSON::ParserError
119
+ nil
120
+ end
121
+ end
122
+ end
123
+ }
124
+
162
125
  # redhat family
163
126
  plat.family('redhat').in_family('linux')
164
127
  .detect {
@@ -325,6 +288,13 @@ module Train::Platforms::Detect::Specifications
325
288
  end
326
289
  }
327
290
 
291
+ # brocade family detected here if device responds to 'uname' command,
292
+ # happens when logging in as root
293
+ plat.family('brocade').title('Brocade Family').in_family('linux')
294
+ .detect {
295
+ !brocade_version.nil?
296
+ }
297
+
328
298
  # genaric linux
329
299
  # this should always be last in the linux family list
330
300
  plat.name('linux').title('Genaric Linux').in_family('linux')
@@ -348,18 +318,6 @@ module Train::Platforms::Detect::Specifications
348
318
  end
349
319
  }
350
320
 
351
- # esx
352
- plat.family('esx').title('ESXi Family')
353
- .detect {
354
- true if unix_uname_s =~ /vmkernel/i
355
- }
356
- plat.name('vmkernel').in_family('esx')
357
- .detect {
358
- @platform[:name] = unix_uname_s.lines[0].chomp
359
- @platform[:release] = unix_uname_r.lines[0].chomp
360
- true
361
- }
362
-
363
321
  # aix
364
322
  plat.family('aix').in_family('unix')
365
323
  .detect {
@@ -475,8 +433,8 @@ module Train::Platforms::Detect::Specifications
475
433
  }
476
434
  plat.family('darwin').in_family('bsd')
477
435
  .detect {
478
- cmd = unix_file_contents('/usr/bin/sw_vers')
479
- if unix_uname_s =~ /darwin/i || !cmd.nil?
436
+ if unix_uname_s =~ /darwin/i
437
+ cmd = unix_file_contents('/usr/bin/sw_vers')
480
438
  unless cmd.nil?
481
439
  m = cmd.match(/^ProductVersion:\s+(.+)$/)
482
440
  @platform[:release] = m.nil? ? nil : m[1]
@@ -523,6 +481,84 @@ module Train::Platforms::Detect::Specifications
523
481
  true
524
482
  end
525
483
  }
484
+
485
+ # arista_eos family
486
+ plat.family('arista_eos').title('Arista EOS Family').in_family('os')
487
+ .detect {
488
+ true
489
+ }
490
+ plat.name('arista_eos').title('Arista EOS').in_family('arista_eos')
491
+ .detect {
492
+ cmd = @backend.run_command('show version | json')
493
+ if cmd.exit_status == 0 && !cmd.stdout.empty?
494
+ require 'json'
495
+ begin
496
+ eos_ver = JSON.parse(cmd.stdout)
497
+ @platform[:release] = eos_ver['version']
498
+ @platform[:arch] = eos_ver['architecture']
499
+ true
500
+ rescue JSON::ParserError
501
+ nil
502
+ end
503
+ end
504
+ }
505
+
506
+ # esx
507
+ plat.family('esx').title('ESXi Family').in_family('os')
508
+ .detect {
509
+ true if unix_uname_s =~ /vmkernel/i
510
+ }
511
+ plat.name('vmkernel').in_family('esx')
512
+ .detect {
513
+ @platform[:name] = unix_uname_s.lines[0].chomp
514
+ @platform[:release] = unix_uname_r.lines[0].chomp
515
+ true
516
+ }
517
+
518
+ # cisco_ios family
519
+ plat.family('cisco').title('Cisco Family').in_family('os')
520
+ .detect {
521
+ !cisco_show_version.nil?
522
+ }
523
+ plat.name('cisco_ios').title('Cisco IOS').in_family('cisco')
524
+ .detect {
525
+ v = cisco_show_version
526
+ next unless v[:type] == 'ios'
527
+ @platform[:release] = v[:version]
528
+ @platform[:arch] = nil
529
+ true
530
+ }
531
+ plat.name('cisco_ios_xe').title('Cisco IOS XE').in_family('cisco')
532
+ .detect {
533
+ v = cisco_show_version
534
+ next unless v[:type] == 'ios-xe'
535
+ @platform[:release] = v[:version]
536
+ @platform[:arch] = nil
537
+ true
538
+ }
539
+ plat.name('cisco_nexus').title('Cisco Nexus').in_family('cisco')
540
+ .detect {
541
+ v = cisco_show_version
542
+ next unless v[:type] == 'nexus'
543
+ @platform[:release] = v[:version]
544
+ @platform[:arch] = nil
545
+ true
546
+ }
547
+
548
+ # brocade family
549
+ plat.family('brocade').title('Brocade Family').in_family('os')
550
+ .detect {
551
+ !brocade_version.nil?
552
+ }
553
+
554
+ plat.name('brocade_fos').title('Brocade FOS').in_family('brocade')
555
+ .detect {
556
+ v = brocade_version
557
+ next unless v[:type] == 'fos'
558
+ @platform[:release] = v[:version]
559
+ @platform[:arch] = nil
560
+ true
561
+ }
526
562
  end
527
563
  end
528
564
  end
@@ -30,7 +30,7 @@ class Train::Plugins
30
30
  # @param [Hash] _options = nil provide optional configuration params
31
31
  # @return [Connection] the connection for this configuration
32
32
  def connection(_options = nil)
33
- fail Train::ClientError, "#{self.class} does not implement #connect()"
33
+ fail Train::ClientError, "#{self.class} does not implement #connection()"
34
34
  end
35
35
 
36
36
  # Register the inheriting class with as a train plugin using the
@@ -43,11 +43,18 @@ module Train::Transports
43
43
 
44
44
  def select_runner(options)
45
45
  if os.windows?
46
+ # Force a 64 bit poweshell if needed
47
+ if RUBY_PLATFORM == 'i386-mingw32' && os.arch == 'x86_64'
48
+ powershell_cmd = "#{ENV['SystemRoot']}\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe"
49
+ else
50
+ powershell_cmd = 'powershell'
51
+ end
52
+
46
53
  # Attempt to use a named pipe but fallback to ShellOut if that fails
47
54
  begin
48
- WindowsPipeRunner.new
55
+ WindowsPipeRunner.new(powershell_cmd)
49
56
  rescue PipeError
50
- WindowsShellRunner.new
57
+ WindowsShellRunner.new(powershell_cmd)
51
58
  end
52
59
  else
53
60
  GenericRunner.new(self, options)
@@ -111,6 +118,10 @@ module Train::Transports
111
118
  require 'json'
112
119
  require 'base64'
113
120
 
121
+ def initialize(powershell_cmd = 'powershell')
122
+ @powershell_cmd = powershell_cmd
123
+ end
124
+
114
125
  def run_command(script)
115
126
  # Prevent progress stream from leaking into stderr
116
127
  script = "$ProgressPreference='SilentlyContinue';" + script
@@ -119,7 +130,7 @@ module Train::Transports
119
130
  script = script.encode('UTF-16LE', 'UTF-8')
120
131
  base64_script = Base64.strict_encode64(script)
121
132
 
122
- cmd = "powershell -NoProfile -EncodedCommand #{base64_script}"
133
+ cmd = "#{@powershell_cmd} -NoProfile -EncodedCommand #{base64_script}"
123
134
 
124
135
  res = Mixlib::ShellOut.new(cmd)
125
136
  res.run_command
@@ -132,7 +143,8 @@ module Train::Transports
132
143
  require 'base64'
133
144
  require 'securerandom'
134
145
 
135
- def initialize
146
+ def initialize(powershell_cmd = 'powershell')
147
+ @powershell_cmd = powershell_cmd
136
148
  @pipe = acquire_pipe
137
149
  fail PipeError if @pipe.nil?
138
150
  end
@@ -206,7 +218,7 @@ module Train::Transports
206
218
 
207
219
  utf8_script = script.encode('UTF-16LE', 'UTF-8')
208
220
  base64_script = Base64.strict_encode64(utf8_script)
209
- cmd = "powershell -NoProfile -ExecutionPolicy bypass -NonInteractive -EncodedCommand #{base64_script}"
221
+ cmd = "#{@powershell_cmd} -NoProfile -ExecutionPolicy bypass -NonInteractive -EncodedCommand #{base64_script}"
210
222
 
211
223
  server_pid = Process.create(command_line: cmd).process_id
212
224
 
@@ -149,6 +149,7 @@ module Train::Transports
149
149
  keys: opts[:key_files],
150
150
  password: opts[:password],
151
151
  forward_agent: opts[:forward_agent],
152
+ proxy_command: opts[:proxy_command],
152
153
  transport_options: opts,
153
154
  }
154
155
 
@@ -65,6 +65,7 @@ class Train::Transports::SSH
65
65
  args += %w{ -o IdentitiesOnly=yes } if options[:keys]
66
66
  args += %W( -o LogLevel=#{level} )
67
67
  args += %W( -o ForwardAgent=#{fwd_agent} ) if options.key?(:forward_agent)
68
+ args += %W( -o ProxyCommand='#{options[:proxy_command]}' ) unless options[:proxy_command].nil?
68
69
  Array(options[:keys]).each do |ssh_key|
69
70
  args += %W( -i #{ssh_key} )
70
71
  end
@@ -113,7 +114,7 @@ class Train::Transports::SSH
113
114
  message: "Waiting for SSH service on #{@hostname}:#{@port}, " \
114
115
  "retrying in #{delay} seconds",
115
116
  )
116
- execute(PING_COMMAND.dup)
117
+ run_command(PING_COMMAND.dup)
117
118
  end
118
119
 
119
120
  def uri
@@ -144,6 +145,11 @@ class Train::Transports::SSH
144
145
  # @api private
145
146
  def establish_connection(opts)
146
147
  logger.debug("[SSH] opening connection to #{self}")
148
+ if @options[:proxy_command]
149
+ require 'net/ssh/proxy/command'
150
+ @options[:proxy] = Net::SSH::Proxy::Command.new(@options[:proxy_command])
151
+ @options.delete(:proxy_command)
152
+ end
147
153
  Net::SSH.start(@hostname, @username, @options.clone.delete_if { |_key, value| value.nil? })
148
154
  rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH => e
149
155
  if (opts[:retries] -= 1) <= 0
@@ -80,7 +80,7 @@ class Train::Transports::WinRM
80
80
  retry_limit: @max_wait_until_ready / delay,
81
81
  retry_delay: delay,
82
82
  )
83
- execute(PING_COMMAND.dup)
83
+ run_command(PING_COMMAND.dup)
84
84
  end
85
85
 
86
86
  def uri
data/lib/train/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
4
 
5
5
  module Train
6
- VERSION = '1.1.1'.freeze
6
+ VERSION = '1.2.0'.freeze
7
7
  end
@@ -204,6 +204,16 @@ describe 'os_detect' do
204
204
  platform[:release].must_equal('12.2')
205
205
  end
206
206
 
207
+ it 'recognizes Cisco IOS XE' do
208
+ mock = Train::Transports::Mock::Connection.new
209
+ mock.mock_command('show version', "Cisco IOS Software, IOS-XE Software, Catalyst L3 Switch Software (CAT3K_CAA-UNIVERSALK9-M), Version 03.03.03SE RELEASE SOFTWARE (fc2)")
210
+ platform = Train::Platforms::Detect.scan(mock)
211
+
212
+ platform[:name].must_equal('cisco_ios_xe')
213
+ platform[:family].must_equal('cisco')
214
+ platform[:release].must_equal('03.03.03SE')
215
+ end
216
+
207
217
  it 'recognizes Cisco Nexus' do
208
218
  mock = Train::Transports::Mock::Connection.new
209
219
  mock.mock_command('show version', "Cisco Nexus Operating System (NX-OS) Software\n system: version 5.2(1)N1(8b)\n")
@@ -214,4 +224,16 @@ describe 'os_detect' do
214
224
  platform[:release].must_equal('5.2')
215
225
  end
216
226
  end
227
+
228
+ describe 'brocade' do
229
+ it 'recognizes Brocade FOS-based SAN switches' do
230
+ mock = Train::Transports::Mock::Connection.new
231
+ mock.mock_command('version', "Kernel: 2.6.14.2\nFabric OS: v7.4.2a\nMade on: Thu Jun 29 19:22:14 2017\nFlash: Sat Sep 9 17:30:42 2017\nBootProm: 1.0.11")
232
+ platform = Train::Platforms::Detect.scan(mock)
233
+
234
+ platform[:name].must_equal('brocade_fos')
235
+ platform[:family].must_equal('brocade')
236
+ platform[:release].must_equal('7.4.2a')
237
+ end
238
+ end
217
239
  end
@@ -50,7 +50,7 @@ describe 'v1 Connection Plugin' do
50
50
  plat.cloud?.must_equal false
51
51
  plat.unix?.must_equal true
52
52
  plat.family.must_equal 'darwin'
53
- plat.family_hierarchy.must_equal ['darwin', 'bsd', 'unix']
53
+ plat.family_hierarchy.must_equal ['darwin', 'bsd', 'unix', 'os']
54
54
  end
55
55
 
56
56
  it 'provides api direct platform' do
@@ -75,7 +75,7 @@ describe 'v1 Connection Plugin' do
75
75
  it 'provides family hierarchy' do
76
76
  plat = Train::Platforms.name('linux')
77
77
  family = connection.family_hierarchy(plat)
78
- family.flatten.must_equal ['linux', 'unix']
78
+ family.flatten.must_equal ['linux', 'unix', 'os']
79
79
  end
80
80
 
81
81
  it 'must use the user-provided logger' do
@@ -14,6 +14,7 @@ describe 'ssh transport' do
14
14
  host: rand.to_s,
15
15
  password: rand.to_s,
16
16
  key_files: rand.to_s,
17
+ proxy_command: 'ssh root@127.0.0.1 -W %h:%p',
17
18
  }}
18
19
  let(:cls_agent) { cls.new({ host: rand.to_s }) }
19
20
 
@@ -95,6 +96,7 @@ describe 'ssh transport' do
95
96
  "-o", "IdentitiesOnly=yes",
96
97
  "-o", "LogLevel=VERBOSE",
97
98
  "-o", "ForwardAgent=no",
99
+ "-o", "ProxyCommand='ssh root@127.0.0.1 -W %h:%p'",
98
100
  "-i", conf[:key_files],
99
101
  "-p", "22",
100
102
  "root@#{conf[:host]}",
@@ -120,6 +122,19 @@ describe 'ssh transport' do
120
122
  cls_agent.stubs(:ssh_known_identities).returns({:some => 'rsa_key'})
121
123
  cls_agent.connection
122
124
  end
125
+
126
+ it 'sets up a proxy when ssh proxy command is specified' do
127
+ mock = MiniTest::Mock.new
128
+ mock.expect(:call, true) do |hostname, username, options|
129
+ options[:proxy].kind_of?(Net::SSH::Proxy::Command) &&
130
+ 'ssh root@127.0.0.1 -W %h:%p' == options[:proxy].command_line_template
131
+ end
132
+ connection.stubs(:run_command)
133
+ Net::SSH.stub(:start, mock) do
134
+ connection.wait_until_ready
135
+ end
136
+ mock.verify
137
+ end
123
138
  end
124
139
 
125
140
  describe 'converting connection to string for logging' do
@@ -154,6 +169,7 @@ describe 'ssh transport' do
154
169
  it 'wont connect if it is not possible' do
155
170
  conf[:host] = 'localhost'
156
171
  conf[:port] = 1
172
+ conf.delete :proxy_command
157
173
  conn = cls.new(conf).connection
158
174
  proc { conn.run_command('uname') }.must_raise Train::Transports::SSHFailed
159
175
  end
@@ -12,16 +12,13 @@ require 'tempfile'
12
12
  require 'train/transports/local'
13
13
 
14
14
  describe 'windows local command' do
15
- let(:conn) {
15
+ let(:backend) do
16
16
  # get final config
17
17
  target_config = Train.target_config({})
18
18
  # initialize train
19
19
  backend = Train.create('local', target_config)
20
-
21
- # start or reuse a connection
22
- conn = backend.connection
23
- conn
24
- }
20
+ end
21
+ let(:conn) { backend.connection }
25
22
 
26
23
  it 'verify os' do
27
24
  os = conn.os
@@ -37,6 +34,65 @@ describe 'windows local command' do
37
34
  cmd.stderr.must_equal ''
38
35
  end
39
36
 
37
+ describe 'force 64 bit powershell command' do
38
+ let(:runner) { conn.instance_variable_get(:@runner) }
39
+ let(:powershell) { runner.instance_variable_get(:@powershell_cmd) }
40
+ RUBY_PLATFORM_DUP = RUBY_PLATFORM.dup
41
+
42
+ def override_platform(platform)
43
+ ::Object.send(:remove_const, :RUBY_PLATFORM)
44
+ ::Object.const_set(:RUBY_PLATFORM, platform)
45
+ end
46
+
47
+ after do
48
+ backend.instance_variable_set(:@connection, nil)
49
+ ::Object.send(:remove_const, :RUBY_PLATFORM)
50
+ ::Object.const_set(:RUBY_PLATFORM, RUBY_PLATFORM_DUP)
51
+ end
52
+
53
+ it 'use normal powershell with PipeRunner' do
54
+ Train::Transports::Local::Connection::WindowsPipeRunner
55
+ .any_instance
56
+ .expects(:acquire_pipe)
57
+ .returns('acquired')
58
+
59
+ override_platform('x64-mingw32')
60
+ powershell.must_equal 'powershell'
61
+ end
62
+
63
+ it 'use 64bit powershell with PipeRunner' do
64
+ Train::Transports::Local::Connection::WindowsPipeRunner
65
+ .any_instance
66
+ .expects(:acquire_pipe)
67
+ .returns('acquired')
68
+
69
+ override_platform('i386-mingw32')
70
+ powershell.must_equal "#{ENV['SystemRoot']}\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe"
71
+ end
72
+
73
+ it 'use normal powershell with ShellRunner' do
74
+ Train::Transports::Local::Connection::WindowsPipeRunner
75
+ .any_instance
76
+ .expects(:acquire_pipe)
77
+ .returns(nil)
78
+
79
+ override_platform('x64-mingw32')
80
+ runner.class.must_equal Train::Transports::Local::Connection::WindowsShellRunner
81
+ powershell.must_equal 'powershell'
82
+ end
83
+
84
+ it 'use 64bit powershell with ShellRunner' do
85
+ Train::Transports::Local::Connection::WindowsPipeRunner
86
+ .any_instance
87
+ .expects(:acquire_pipe)
88
+ .returns(nil)
89
+
90
+ override_platform('i386-mingw32')
91
+ runner.class.must_equal Train::Transports::Local::Connection::WindowsShellRunner
92
+ powershell.must_equal "#{ENV['SystemRoot']}\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe"
93
+ end
94
+ end
95
+
40
96
  it 'use powershell piping' do
41
97
  cmd = conn.run_command("New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name A -Value (Write-Output 'PropertyA') -PassThru | Add-Member -MemberType NoteProperty -Name B -Value (Write-Output 'PropertyB') -PassThru | ConvertTo-Json")
42
98
  cmd.stdout.must_equal "{\r\n \"A\": \"PropertyA\",\r\n \"B\": \"PropertyB\"\r\n}\r\n"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: train
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-14 00:00:00.000000000 Z
11
+ date: 2018-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -316,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
316
  version: '0'
317
317
  requirements: []
318
318
  rubyforge_project:
319
- rubygems_version: 2.5.2
319
+ rubygems_version: 2.6.14
320
320
  signing_key:
321
321
  specification_version: 4
322
322
  summary: Transport interface to talk to different backends.