train 0.19.1 → 0.20.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: a52a5c7ef67219ce7efa1358a142c6a26d400d61
4
- data.tar.gz: 0e4a108030e0164506191a128463d691cdbfa177
3
+ metadata.gz: e2e42871db47191abec6fe3d94b56a60863abd48
4
+ data.tar.gz: 9004baaebe7b8021f840647bdc5032b88fb130fc
5
5
  SHA512:
6
- metadata.gz: 58bc527291b454cdd415a2c39fdc3166e010b2b5106f4917b5b845933612d6b9ea01914dafb932eea0760157c925d2f58abb1cd6be626f513c165a37db12acdd
7
- data.tar.gz: d67667d29a6cb0bebe830c0c6c4d8706c4c15054ecc7eae6c1f774d0d8c58b9ed51bce96dd4e807444210419e98ff15a6b47ad2d04d4b35240908d87b9948ba0
6
+ metadata.gz: 32c7d11c6aeaee6a856dfa3ce914e8d6a64d23108d8239473a7364b82929cace43c495f21765486d5b4fec02911c67747075376bde4ed8239fb88c54d30cac6d
7
+ data.tar.gz: 1335190030d7f53d31b7c5ee4f7c882fc101e80b9ae808da030c4090ecac2cc95a1b609049dbccd78ab9e7235a1c649dc9a206700de9c4689c2c1b890425f77f
@@ -69,3 +69,5 @@ Style/SpaceAroundOperators:
69
69
  Enabled: false
70
70
  Style/IfUnlessModifier:
71
71
  Enabled: false
72
+ Style/FrozenStringLiteralComment:
73
+ Enabled: false
@@ -1,7 +1,20 @@
1
1
  # Change Log
2
2
 
3
- ## [0.19.1](https://github.com/chef/train/tree/0.19.1) (2016-09-16)
4
- [Full Changelog](https://github.com/chef/train/compare/v0.19.0...0.19.1)
3
+ ## [0.20.0](https://github.com/chef/train/tree/0.20.0) (2016-09-21)
4
+ [Full Changelog](https://github.com/chef/train/compare/v0.19.1...0.20.0)
5
+
6
+ **Fixed bugs:**
7
+
8
+ - get `Preparing modules for first use.` when I use train on Windows [\#153](https://github.com/chef/train/issues/153)
9
+
10
+ **Merged pull requests:**
11
+
12
+ - `Preparing modules for first use.` error message on Windows [\#152](https://github.com/chef/train/pull/152) ([chris-rock](https://github.com/chris-rock))
13
+ - Convert `wmic` architecture to a normal standard [\#151](https://github.com/chef/train/pull/151) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
14
+ - Login shell [\#149](https://github.com/chef/train/pull/149) ([jonathanmorley](https://github.com/jonathanmorley))
15
+
16
+ ## [v0.19.1](https://github.com/chef/train/tree/v0.19.1) (2016-09-16)
17
+ [Full Changelog](https://github.com/chef/train/compare/v0.19.0...v0.19.1)
5
18
 
6
19
  **Implemented enhancements:**
7
20
 
@@ -28,6 +28,9 @@ module Train::Extras
28
28
  class LinuxCommand < CommandWrapperBase
29
29
  Train::Options.attach(self)
30
30
 
31
+ option :shell, default: false
32
+ option :shell_options, default: nil
33
+ option :shell_command, default: nil
31
34
  option :sudo, default: false
32
35
  option :sudo_options, default: nil
33
36
  option :sudo_password, default: nil
@@ -38,12 +41,14 @@ module Train::Extras
38
41
  @backend = backend
39
42
  validate_options(options)
40
43
 
44
+ @shell = options[:shell]
45
+ @shell_options = options[:shell_options] # e.g. '--login'
46
+ @shell_command = options[:shell_command] # e.g. '/bin/sh'
41
47
  @sudo = options[:sudo]
42
48
  @sudo_options = options[:sudo_options]
43
49
  @sudo_password = options[:sudo_password]
44
50
  @sudo_command = options[:sudo_command]
45
51
  @user = options[:user]
46
- @prefix = build_prefix
47
52
  end
48
53
 
49
54
  # (see CommandWrapperBase::verify)
@@ -71,29 +76,48 @@ module Train::Extras
71
76
 
72
77
  # (see CommandWrapperBase::run)
73
78
  def run(command)
74
- @prefix + command
79
+ shell_wrap(sudo_wrap(command))
75
80
  end
76
81
 
77
82
  def self.active?(options)
78
- options.is_a?(Hash) && options[:sudo]
83
+ options.is_a?(Hash) && (
84
+ options[:sudo] ||
85
+ options[:shell]
86
+ )
79
87
  end
80
88
 
81
89
  private
82
90
 
83
- def build_prefix
84
- return '' unless @sudo
85
- return '' if @user == 'root'
91
+ # wrap the cmd in a sudo command
92
+ def sudo_wrap(cmd)
93
+ return cmd unless @sudo
94
+ return cmd if @user == 'root'
86
95
 
87
96
  res = (@sudo_command || 'sudo') + ' '
88
97
 
89
- unless @sudo_password.nil?
90
- b64pw = Base64.strict_encode64(@sudo_password + "\n")
91
- res = "echo #{b64pw} | base64 --decode | #{res}-S "
92
- end
98
+ res = "#{safe_string(@sudo_password + "\n")} | #{res}-S " unless @sudo_password.nil?
93
99
 
94
100
  res << @sudo_options.to_s + ' ' unless @sudo_options.nil?
95
101
 
96
- res
102
+ res + cmd
103
+ end
104
+
105
+ # wrap the cmd in a subshell allowing for options to
106
+ # passed to the subshell
107
+ def shell_wrap(cmd)
108
+ return cmd unless @shell
109
+
110
+ shell = @shell_command || '$SHELL'
111
+ options = ' ' + @shell_options.to_s unless @shell_options.nil?
112
+
113
+ "#{safe_string(cmd)} | #{shell}#{options}"
114
+ end
115
+
116
+ # encapsulates encoding the string into a safe form, and decoding for use.
117
+ # @return [String] A command line snippet that can be used as part of a pipeline.
118
+ def safe_string(str)
119
+ b64str = Base64.strict_encode64(str)
120
+ "echo #{b64str} | base64 --decode"
97
121
  end
98
122
  end
99
123
 
@@ -113,7 +137,7 @@ module Train::Extras
113
137
  # especially in local mode, we cannot be sure that we get a Powershell
114
138
  # we may just get a `cmd`.
115
139
  # TODO: we may want to opt for powershell.exe -command instead of `encodeCommand`
116
- "powershell -encodedCommand #{encoded(safe_script(script))}"
140
+ "powershell -NoProfile -encodedCommand #{encoded(safe_script(script))}"
117
141
  end
118
142
 
119
143
  # suppress the progress stream from leaking to stderr
@@ -50,8 +50,37 @@ module Train::Extras
50
50
  @platform[:build] = sys_info[:BuildNumber]
51
51
  @platform[:name] = sys_info[:Caption]
52
52
  @platform[:name] = @platform[:name].gsub('Microsoft', '').strip unless @platform[:name].empty?
53
- @platform[:arch] = sys_info[:OSArchitecture]
53
+ @platform[:arch] = read_wmic_cpu
54
54
  end
55
55
  end
56
+
57
+ # `OSArchitecture` from `read_wmic` does not match a normal standard
58
+ # For example, `x86_64` shows as `64-bit`
59
+ def read_wmic_cpu
60
+ res = @backend.run_command('wmic cpu get architecture /format:list')
61
+ if res.exit_status == 0
62
+ sys_info = {}
63
+ res.stdout.lines.each { |line|
64
+ m = /^\s*([^=]*?)\s*=\s*(.*?)\s*$/.match(line)
65
+ sys_info[m[1].to_sym] = m[2] unless m.nil? || m[1].nil?
66
+ }
67
+ end
68
+
69
+ # This converts `wmic os get architecture` output to a normal standard
70
+ # https://msdn.microsoft.com/en-us/library/aa394373(VS.85).aspx
71
+ arch_map = {
72
+ 0 => 'i386',
73
+ 1 => 'mips',
74
+ 2 => 'alpha',
75
+ 3 => 'powerpc',
76
+ 5 => 'arm',
77
+ 6 => 'ia64',
78
+ 9 => 'x86_64',
79
+ }
80
+
81
+ # The value of `wmic cpu get architecture` is always a number between 0-9
82
+ arch_number = sys_info[:Architecture].to_i
83
+ arch_map[arch_number]
84
+ end
56
85
  end
57
86
  end
@@ -3,5 +3,5 @@
3
3
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
4
 
5
5
  module Train
6
- VERSION = '0.19.1'.freeze
6
+ VERSION = '0.20.0'.freeze
7
7
  end
@@ -16,47 +16,95 @@ describe 'linux command' do
16
16
  backend
17
17
  }
18
18
 
19
- it 'wraps commands in sudo' do
20
- lc = cls.new(backend, { sudo: true })
21
- lc.run(cmd).must_equal "sudo #{cmd}"
22
- end
19
+ describe 'sudo wrapping' do
20
+ it 'wraps commands in sudo' do
21
+ lc = cls.new(backend, { sudo: true })
22
+ lc.run(cmd).must_equal "sudo #{cmd}"
23
+ end
23
24
 
24
- it 'doesnt wrap commands in sudo if user == root' do
25
- lc = cls.new(backend, { sudo: true, user: 'root' })
26
- lc.run(cmd).must_equal cmd
27
- end
25
+ it 'doesnt wrap commands in sudo if user == root' do
26
+ lc = cls.new(backend, { sudo: true, user: 'root' })
27
+ lc.run(cmd).must_equal cmd
28
+ end
28
29
 
29
- it 'wraps commands in sudo with all options' do
30
- opts = rand.to_s
31
- lc = cls.new(backend, { sudo: true, sudo_options: opts })
32
- lc.run(cmd).must_equal "sudo #{opts} #{cmd}"
33
- end
30
+ it 'wraps commands in sudo with all options' do
31
+ opts = rand.to_s
32
+ lc = cls.new(backend, { sudo: true, sudo_options: opts })
33
+ lc.run(cmd).must_equal "sudo #{opts} #{cmd}"
34
+ end
34
35
 
35
- it 'runs commands in sudo with password' do
36
- pw = rand.to_s
37
- lc = cls.new(backend, { sudo: true, sudo_password: pw })
38
- bpw = Base64.strict_encode64(pw + "\n")
39
- lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | sudo -S #{cmd}"
40
- end
36
+ it 'runs commands in sudo with password' do
37
+ pw = rand.to_s
38
+ lc = cls.new(backend, { sudo: true, sudo_password: pw })
39
+ bpw = Base64.strict_encode64(pw + "\n")
40
+ lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | sudo -S #{cmd}"
41
+ end
41
42
 
42
- it 'wraps commands in sudo_command instead of sudo' do
43
- sudo_command = rand.to_s
44
- lc = cls.new(backend, { sudo: true, sudo_command: sudo_command })
45
- lc.run(cmd).must_equal "#{sudo_command} #{cmd}"
46
- end
43
+ it 'wraps commands in sudo_command instead of sudo' do
44
+ sudo_command = rand.to_s
45
+ lc = cls.new(backend, { sudo: true, sudo_command: sudo_command })
46
+ lc.run(cmd).must_equal "#{sudo_command} #{cmd}"
47
+ end
48
+
49
+ it 'wraps commands in sudo_command with all options' do
50
+ opts = rand.to_s
51
+ sudo_command = rand.to_s
52
+ lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_options: opts })
53
+ lc.run(cmd).must_equal "#{sudo_command} #{opts} #{cmd}"
54
+ end
47
55
 
48
- it 'wraps commands in sudo_command with all options' do
49
- opts = rand.to_s
50
- sudo_command = rand.to_s
51
- lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_options: opts })
52
- lc.run(cmd).must_equal "#{sudo_command} #{opts} #{cmd}"
56
+ it 'runs commands in sudo_command with password' do
57
+ pw = rand.to_s
58
+ sudo_command = rand.to_s
59
+ lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_password: pw })
60
+ bpw = Base64.strict_encode64(pw + "\n")
61
+ lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | #{sudo_command} -S #{cmd}"
62
+ end
53
63
  end
54
64
 
55
- it 'runs commands in sudo_command with password' do
56
- pw = rand.to_s
57
- sudo_command = rand.to_s
58
- lc = cls.new(backend, { sudo: true, sudo_command: sudo_command, sudo_password: pw })
59
- bpw = Base64.strict_encode64(pw + "\n")
60
- lc.run(cmd).must_equal "echo #{bpw} | base64 --decode | #{sudo_command} -S #{cmd}"
65
+ describe 'shell wrapping' do
66
+ it 'wraps commands in a default shell with login' do
67
+ lc = cls.new(backend, { shell: true, shell_options: '--login' })
68
+ bcmd = Base64.strict_encode64(cmd)
69
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
70
+ end
71
+
72
+ it 'wraps sudo commands in a default shell with login' do
73
+ lc = cls.new(backend, { sudo: true, shell: true, shell_options: '--login' })
74
+ bcmd = Base64.strict_encode64("sudo #{cmd}")
75
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
76
+ end
77
+
78
+ it 'wraps sudo commands and sudo passwords in a default shell with login' do
79
+ pw = rand.to_s
80
+ lc = cls.new(backend, { sudo: true, sudo_password: pw, shell: true, shell_options: '--login' })
81
+ bpw = Base64.strict_encode64(pw + "\n")
82
+ bcmd = Base64.strict_encode64("echo #{bpw} | base64 --decode | sudo -S #{cmd}")
83
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | $SHELL --login"
84
+ p bcmd
85
+ end
86
+
87
+ it 'wraps commands in a default shell when shell is true' do
88
+ lc = cls.new(backend, { shell: true })
89
+ bcmd = Base64.strict_encode64(cmd)
90
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | $SHELL"
91
+ end
92
+
93
+ it 'doesnt wrap commands in a shell when shell is false' do
94
+ lc = cls.new(backend, { shell: false })
95
+ lc.run(cmd).must_equal cmd
96
+ end
97
+
98
+ it 'wraps commands in a `shell` instead of default shell' do
99
+ lc = cls.new(backend, { shell: true, shell_command: '/bin/bash' })
100
+ bcmd = Base64.strict_encode64(cmd)
101
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | /bin/bash"
102
+ end
103
+
104
+ it 'wraps commands in a default shell with login' do
105
+ lc = cls.new(backend, { shell: true, shell_command: '/bin/bash', shell_options: '--login' })
106
+ bcmd = Base64.strict_encode64(cmd)
107
+ lc.run(cmd).must_equal "echo #{bcmd} | base64 --decode | /bin/bash --login"
108
+ end
61
109
  end
62
110
  end
@@ -17,6 +17,7 @@ describe 'os_detect_windows' do
17
17
  detector = OsDetectWindowsTester.new
18
18
  detector.backend.mock_command('cmd /c ver', "\r\nMicrosoft Windows [Version 6.3.9600]\r\n", '', 0)
19
19
  detector.backend.mock_command('wmic os get * /format:list',"\r\r\nBuildNumber=9600\r\r\nCaption=Microsoft Windows Server 2012 R2 Standard\r\r\nOSArchitecture=64-bit\r\r\nVersion=6.3.9600\r\r\n" , '', 0)
20
+ detector.backend.mock_command('wmic cpu get architecture /format:list',"\r\r\nArchitecture=9\r\r\n" , '', 0)
20
21
  detector
21
22
  }
22
23
 
@@ -24,7 +25,7 @@ describe 'os_detect_windows' do
24
25
  detector.detect_windows
25
26
  detector.platform[:family].must_equal('windows')
26
27
  detector.platform[:name].must_equal('Windows Server 2012 R2 Standard')
27
- detector.platform[:arch].must_equal('64-bit')
28
+ detector.platform[:arch].must_equal('x86_64')
28
29
  detector.platform[:release].must_equal('6.3.9600')
29
30
  end
30
31
  end
@@ -34,6 +35,7 @@ describe 'os_detect_windows' do
34
35
  detector = OsDetectWindowsTester.new
35
36
  detector.backend.mock_command('cmd /c ver', "\r\nMicrosoft Windows [Version 6.1.7601]\r\n", '', 0)
36
37
  detector.backend.mock_command('wmic os get * /format:list',"\r\r\nBuildNumber=7601\r\r\nCaption=Microsoft Windows Server 2008 R2 Standard \r\r\nOSArchitecture=64-bit\r\r\nVersion=6.1.7601\r\r\n" , '', 0)
38
+ detector.backend.mock_command('wmic cpu get architecture /format:list',"\r\r\nArchitecture=9\r\r\n" , '', 0)
37
39
  detector
38
40
  }
39
41
 
@@ -41,7 +43,7 @@ describe 'os_detect_windows' do
41
43
  detector.detect_windows
42
44
  detector.platform[:family].must_equal('windows')
43
45
  detector.platform[:name].must_equal('Windows Server 2008 R2 Standard')
44
- detector.platform[:arch].must_equal('64-bit')
46
+ detector.platform[:arch].must_equal('x86_64')
45
47
  detector.platform[:release].must_equal('6.1.7601')
46
48
  end
47
49
  end
@@ -51,6 +53,7 @@ describe 'os_detect_windows' do
51
53
  detector = OsDetectWindowsTester.new
52
54
  detector.backend.mock_command('cmd /c ver', "\r\nMicrosoft Windows [Version 6.1.7601]\r\n", '', 0)
53
55
  detector.backend.mock_command('wmic os get * /format:list',"\r\r\nBuildNumber=7601\r\r\nCaption=Microsoft Windows 7 Enterprise \r\r\nOSArchitecture=32-bit\r\r\nVersion=6.1.7601\r\r\n\r\r\n" , '', 0)
56
+ detector.backend.mock_command('wmic cpu get architecture /format:list',"\r\r\nArchitecture=0\r\r\n" , '', 0)
54
57
  detector
55
58
  }
56
59
 
@@ -58,7 +61,7 @@ describe 'os_detect_windows' do
58
61
  detector.detect_windows
59
62
  detector.platform[:family].must_equal('windows')
60
63
  detector.platform[:name].must_equal('Windows 7 Enterprise')
61
- detector.platform[:arch].must_equal('32-bit')
64
+ detector.platform[:arch].must_equal('i386')
62
65
  detector.platform[:release].must_equal('6.1.7601')
63
66
  end
64
67
  end
@@ -68,6 +71,7 @@ describe 'os_detect_windows' do
68
71
  detector = OsDetectWindowsTester.new
69
72
  detector.backend.mock_command('cmd /c ver', "\r\nMicrosoft Windows [Version 10.0.10240]\r\n", '', 0)
70
73
  detector.backend.mock_command('wmic os get * /format:list',"\r\r\nBuildNumber=10240\r\r\nCaption=Microsoft Windows 10 Pro\r\r\nOSArchitecture=64-bit\r\r\nVersion=10.0.10240\r\r\n\r\r\n" , '', 0)
74
+ detector.backend.mock_command('wmic cpu get architecture /format:list',"\r\r\nArchitecture=9\r\r\n" , '', 0)
71
75
  detector
72
76
  }
73
77
 
@@ -75,7 +79,7 @@ describe 'os_detect_windows' do
75
79
  detector.detect_windows
76
80
  detector.platform[:family].must_equal('windows')
77
81
  detector.platform[:name].must_equal('Windows 10 Pro')
78
- detector.platform[:arch].must_equal('64-bit')
82
+ detector.platform[:arch].must_equal('x86_64')
79
83
  detector.platform[:release].must_equal('10.0.10240')
80
84
  end
81
85
  end
@@ -84,7 +88,8 @@ describe 'os_detect_windows' do
84
88
  let(:detector) {
85
89
  detector = OsDetectWindowsTester.new
86
90
  detector.backend.mock_command('cmd /c ver', "\r\nMicrosoft Windows [Version 4.10.1998]\r\n", '', 0)
87
- detector.backend.mock_command('wmic os get * /format:list', nil , '', 1)
91
+ detector.backend.mock_command('wmic os get * /format:list', nil, '', 1)
92
+ detector.backend.mock_command('wmic cpu get architecture /format:list', nil, '', 1)
88
93
  detector
89
94
  }
90
95
 
@@ -24,7 +24,7 @@ describe 'windows local command' do
24
24
  os[:name].must_equal 'Windows Server 2012 R2 Datacenter'
25
25
  os[:family].must_equal "windows"
26
26
  os[:release].must_equal '6.3.9600'
27
- os[:arch].must_equal '64-bit'
27
+ os[:arch].must_equal 'x86_64'
28
28
  end
29
29
 
30
30
  it 'run echo test' do
@@ -30,7 +30,7 @@ describe 'windows winrm command' do
30
30
  os[:name].must_equal 'Windows Server 2012 R2 Datacenter'
31
31
  os[:family].must_equal 'windows'
32
32
  os[:release].must_equal '6.3.9600'
33
- os[:arch].must_equal '64-bit'
33
+ os[:arch].must_equal 'x86_64'
34
34
  end
35
35
 
36
36
  it 'run echo test' do
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: 0.19.1
4
+ version: 0.20.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: 2016-09-16 00:00:00.000000000 Z
11
+ date: 2016-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json