train 0.28.0 → 0.29.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -2
  3. data/lib/train/extras.rb +0 -5
  4. data/lib/train/extras/os_common.rb +1 -1
  5. data/lib/train/extras/os_detect_unix.rb +6 -0
  6. data/lib/train/{extras/file_common.rb → file.rb} +65 -92
  7. data/lib/train/file/local.rb +70 -0
  8. data/lib/train/file/local/unix.rb +77 -0
  9. data/lib/train/file/local/windows.rb +63 -0
  10. data/lib/train/file/remote.rb +28 -0
  11. data/lib/train/file/remote/aix.rb +21 -0
  12. data/lib/train/file/remote/linux.rb +19 -0
  13. data/lib/train/file/remote/qnx.rb +41 -0
  14. data/lib/train/file/remote/unix.rb +110 -0
  15. data/lib/train/file/remote/windows.rb +94 -0
  16. data/lib/train/plugins/base_connection.rb +2 -1
  17. data/lib/train/transports/docker.rb +8 -1
  18. data/lib/train/transports/local.rb +6 -2
  19. data/lib/train/transports/mock.rb +7 -6
  20. data/lib/train/transports/ssh.rb +1 -2
  21. data/lib/train/transports/ssh_connection.rb +24 -4
  22. data/lib/train/transports/winrm_connection.rb +11 -5
  23. data/lib/train/version.rb +1 -1
  24. data/test/integration/tests/path_block_device_test.rb +2 -2
  25. data/test/integration/tests/path_character_device_test.rb +2 -2
  26. data/test/integration/tests/path_file_test.rb +2 -2
  27. data/test/integration/tests/path_folder_test.rb +5 -5
  28. data/test/integration/tests/path_missing_test.rb +0 -1
  29. data/test/integration/tests/path_pipe_test.rb +2 -3
  30. data/test/integration/tests/path_symlink_test.rb +2 -2
  31. data/test/unit/extras/os_detect_linux_test.rb +3 -3
  32. data/test/unit/extras/os_detect_windows_test.rb +1 -1
  33. data/test/unit/file/local/unix_test.rb +112 -0
  34. data/test/unit/file/local/windows_test.rb +41 -0
  35. data/test/unit/file/local_test.rb +110 -0
  36. data/test/unit/{extras/linux_file_test.rb → file/remote/linux_test.rb} +7 -7
  37. data/test/unit/file/remote/unix_test.rb +44 -0
  38. data/test/unit/file/remote_test.rb +62 -0
  39. data/test/unit/file_test.rb +156 -0
  40. data/test/unit/plugins/transport_test.rb +1 -1
  41. data/test/unit/transports/mock_test.rb +3 -3
  42. data/test/windows/local_test.rb +106 -0
  43. data/test/windows/winrm_test.rb +125 -0
  44. metadata +26 -16
  45. data/lib/train/extras/file_aix.rb +0 -20
  46. data/lib/train/extras/file_linux.rb +0 -16
  47. data/lib/train/extras/file_unix.rb +0 -79
  48. data/lib/train/extras/file_windows.rb +0 -100
  49. data/lib/train/transports/local_file.rb +0 -98
  50. data/test/unit/extras/file_common_test.rb +0 -180
  51. data/test/unit/extras/windows_file_test.rb +0 -44
  52. data/test/unit/transports/local_file_test.rb +0 -202
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eca87a39cc3d6258174e753e4533c05f9508ac24
4
- data.tar.gz: 82689ec956034e7e19b96d0f749bced3964c7fa7
3
+ metadata.gz: b82f61f801217ce81fc40bb5ad6a6e73a19da3de
4
+ data.tar.gz: 25fb11d1d6930ecda79bb5d2e70030ddddcf976b
5
5
  SHA512:
6
- metadata.gz: e984b1624f89dee67e5dbf0014db3b3d7f40b3a24a7a68bc1e5bfdb212c080940427ca167df8799f3fa1b54ae7c801791661e8d000e497de853703e5fcb4b01d
7
- data.tar.gz: 67639d931b4d15c01ef5feafdc80c2bba5b02b3f78d6ec90d04124cb7e2d195475c17d14d52e3070bf07720b8a3d433b25effa88a3dba03ec5ef901952696301
6
+ metadata.gz: 1c752a556c55eadeaec19702a6db9ba3110b17b55418f3301a04d919ae899a3e806ed716ce5239515f33efb203e98d6678a8d0bed0f515a8cf0e4cbf22e1dc9f
7
+ data.tar.gz: 51098591df48b28d34798dbf729c701f903889e55d63f48a38115aeea0a94d2eca48bcc32bba33b398700574f66db6d7f980aa2e50b1b9fda528edba9b96cba6
@@ -1,10 +1,25 @@
1
1
  # Change Log
2
2
 
3
- ## [0.28.0](https://github.com/chef/train/tree/0.28.0) (2017-09-25)
4
- [Full Changelog](https://github.com/chef/train/compare/v0.27.0...0.28.0)
3
+ ## [0.29.0](https://github.com/chef/train/tree/0.29.0) (2017-11-13)
4
+ [Full Changelog](https://github.com/chef/train/compare/v0.28.0...0.29.0)
5
5
 
6
6
  **Merged pull requests:**
7
7
 
8
+ - Reverting accidental push to master re: \#204 [\#208](https://github.com/chef/train/pull/208) ([adamleff](https://github.com/adamleff))
9
+ - clearer error if no auth methods are available [\#207](https://github.com/chef/train/pull/207) ([thommay](https://github.com/thommay))
10
+ - Build a complete mock OS object [\#206](https://github.com/chef/train/pull/206) ([adamleff](https://github.com/adamleff))
11
+ - Platform framework and detect DSL [\#204](https://github.com/chef/train/pull/204) ([jquick](https://github.com/jquick))
12
+ - add basic qnx support for train [\#203](https://github.com/chef/train/pull/203) ([chris-rock](https://github.com/chris-rock))
13
+ - Add CODEOWNERS for train [\#202](https://github.com/chef/train/pull/202) ([adamleff](https://github.com/adamleff))
14
+ - implement uploads and downloads for ssh and winrm [\#201](https://github.com/chef/train/pull/201) ([thommay](https://github.com/thommay))
15
+ - \[MSYS-649\] Fix InSpec file size in Windows, refactor File classes [\#193](https://github.com/chef/train/pull/193) ([Vasu1105](https://github.com/Vasu1105))
16
+
17
+ ## [v0.28.0](https://github.com/chef/train/tree/v0.28.0) (2017-09-25)
18
+ [Full Changelog](https://github.com/chef/train/compare/v0.27.0...v0.28.0)
19
+
20
+ **Merged pull requests:**
21
+
22
+ - Release 0.28.0 [\#200](https://github.com/chef/train/pull/200) ([adamleff](https://github.com/adamleff))
8
23
  - Continue to support older net-ssh while fixing 4.2 deprecation [\#199](https://github.com/chef/train/pull/199) ([adamleff](https://github.com/adamleff))
9
24
 
10
25
  ## [v0.27.0](https://github.com/chef/train/tree/v0.27.0) (2017-09-25)
@@ -4,11 +4,6 @@
4
4
 
5
5
  module Train::Extras
6
6
  require 'train/extras/command_wrapper'
7
- require 'train/extras/file_common'
8
- require 'train/extras/file_unix'
9
- require 'train/extras/file_aix'
10
- require 'train/extras/file_linux'
11
- require 'train/extras/file_windows'
12
7
  require 'train/extras/os_common'
13
8
  require 'train/extras/stat'
14
9
 
@@ -71,7 +71,7 @@ module Train::Extras
71
71
 
72
72
  OS['linux'] = %w{linux alpine arch coreos exherbo gentoo slackware fedora amazon} + OS['redhat'] + OS['debian'] + OS['suse']
73
73
 
74
- OS['unix'] = %w{unix aix hpux} + OS['linux'] + OS['solaris'] + OS['bsd']
74
+ OS['unix'] = %w{unix aix hpux qnx} + OS['linux'] + OS['solaris'] + OS['bsd']
75
75
 
76
76
  # Helper methods to check the OS type
77
77
  # Provides methods in the form of: linux?, unix?, solaris? ...
@@ -41,6 +41,12 @@ module Train::Extras
41
41
  @platform[:name] = uname_s.lines[0].chomp
42
42
  @platform[:release] = uname_r.lines[0].chomp
43
43
 
44
+ when /qnx/
45
+ @platform[:family] = 'qnx'
46
+ @platform[:name] = uname_s.lines[0].chomp.downcase
47
+ @platform[:release] = uname_r.lines[0].chomp
48
+ @platform[:arch] = uname_m
49
+
44
50
  when /sunos/
45
51
  detect_solaris
46
52
  else
@@ -1,17 +1,39 @@
1
1
  # encoding: utf-8
2
- # author: Dominik Richter
2
+ #
3
3
  # author: Christoph Hartmann
4
+ # author: Dominik Richter
4
5
 
6
+ require 'train/file/local'
7
+ require 'train/file/local/unix'
8
+ require 'train/file/local/windows'
9
+ require 'train/file/remote'
10
+ require 'train/file/remote/unix'
11
+ require 'train/file/remote/linux'
12
+ require 'train/file/remote/windows'
13
+ require 'train/file/remote/qnx'
5
14
  require 'digest/sha2'
6
15
  require 'digest/md5'
16
+ require 'train/extras/stat'
17
+
18
+ module Train
19
+ class File
20
+ def initialize(backend, path, follow_symlink = true)
21
+ @backend = backend
22
+ @path = path || ''
23
+ @follow_symlink = follow_symlink
24
+
25
+ sanitize_filename(path)
26
+ end
27
+
28
+ # This method gets override by particular os class.
29
+ def sanitize_filename(_path)
30
+ nil
31
+ end
7
32
 
8
- module Train::Extras
9
- class FileCommon # rubocop:disable Metrics/ClassLength
10
33
  # interface methods: these fields should be implemented by every
11
34
  # backend File
12
35
  DATA_FIELDS = %w{
13
36
  exist? mode owner group uid gid content mtime size selinux_label path
14
- product_version file_version
15
37
  }.freeze
16
38
 
17
39
  DATA_FIELDS.each do |m|
@@ -20,12 +42,6 @@ module Train::Extras
20
42
  end
21
43
  end
22
44
 
23
- def initialize(backend, path, follow_symlink = true)
24
- @backend = backend
25
- @path = path || ''
26
- @follow_symlink = follow_symlink
27
- end
28
-
29
45
  def to_json
30
46
  res = Hash[DATA_FIELDS.map { |x| [x, method(x).call] }]
31
47
  # additional fields provided as input
@@ -38,9 +54,6 @@ module Train::Extras
38
54
  :unknown
39
55
  end
40
56
 
41
- # The following methods can be overwritten by a derived class
42
- # if desired, to e.g. achieve optimizations.
43
-
44
57
  def md5sum
45
58
  res = Digest::MD5.new
46
59
  res.update(content)
@@ -57,36 +70,6 @@ module Train::Extras
57
70
  nil
58
71
  end
59
72
 
60
- # Additional methods for convenience
61
-
62
- def file?
63
- type.to_s == 'file'
64
- end
65
-
66
- def block_device?
67
- type.to_s == 'block_device'
68
- end
69
-
70
- def character_device?
71
- type.to_s == 'character_device'
72
- end
73
-
74
- def socket?
75
- type.to_s == 'socket'
76
- end
77
-
78
- def directory?
79
- type.to_s == 'directory'
80
- end
81
-
82
- def symlink?
83
- source.type.to_s == 'symlink'
84
- end
85
-
86
- def source_path
87
- @path
88
- end
89
-
90
73
  def source
91
74
  if @follow_symlink
92
75
  self.class.new(@backend, @path, false)
@@ -95,28 +78,22 @@ module Train::Extras
95
78
  end
96
79
  end
97
80
 
98
- def pipe?
99
- type == :pipe
100
- end
101
-
102
- def mode?(sth)
103
- mode == sth
104
- end
105
-
106
- def owned_by?(sth)
107
- owner == sth
108
- end
109
-
110
- def grouped_into?(sth)
111
- group == sth
81
+ def source_path
82
+ @path
112
83
  end
113
84
 
114
- def linked_to?(dst)
115
- link_path == dst
85
+ # product_version is primarily used by Windows operating systems only and will be overwritten
86
+ # in Windows-related classes. Since this field is returned for all file objects, the acceptable
87
+ # default value is nil
88
+ def product_version
89
+ nil
116
90
  end
117
91
 
118
- def link_path
119
- symlink? ? path : nil
92
+ # file_version is primarily used by Windows operating systems only and will be overwritten
93
+ # in Windows-related classes. Since this field is returned for all file objects, the acceptable
94
+ # default value is nil
95
+ def file_version
96
+ nil
120
97
  end
121
98
 
122
99
  def version?(version)
@@ -124,48 +101,44 @@ module Train::Extras
124
101
  file_version == version
125
102
  end
126
103
 
127
- def unix_mode_mask(owner, type)
128
- o = UNIX_MODE_OWNERS[owner.to_sym]
129
- return nil if o.nil?
130
-
131
- t = UNIX_MODE_TYPES[type.to_sym]
132
- return nil if t.nil?
104
+ def block_device?
105
+ type.to_s == 'block_device'
106
+ end
133
107
 
134
- t & o
108
+ def character_device?
109
+ type.to_s == 'character_device'
135
110
  end
136
111
 
137
- def mounted?
138
- !mounted.nil? && !mounted.stdout.nil? && !mounted.stdout.empty?
112
+ def pipe?
113
+ type.to_s == 'pipe'
139
114
  end
140
115
 
141
- def basename(suffix = nil, sep = '/')
142
- fail 'Not yet supported: Suffix in file.basename' unless suffix.nil?
143
- @basename ||= detect_filename(path, sep || '/')
116
+ def file?
117
+ type.to_s == 'file'
144
118
  end
145
119
 
146
- # helper methods provided to any implementing class
120
+ def socket?
121
+ type.to_s == 'socket'
122
+ end
147
123
 
148
- private
124
+ def directory?
125
+ type.to_s == 'directory'
126
+ end
149
127
 
150
- def detect_filename(path, sep)
151
- idx = path.rindex(sep)
152
- return path if idx.nil?
153
- idx += 1
154
- return detect_filename(path[0..-2], sep) if idx == path.length
155
- path[idx..-1]
128
+ def symlink?
129
+ source.type.to_s == 'symlink'
156
130
  end
157
131
 
158
- UNIX_MODE_OWNERS = {
159
- all: 00777,
160
- owner: 00700,
161
- group: 00070,
162
- other: 00007,
163
- }.freeze
132
+ def owned_by?(sth)
133
+ owner == sth
134
+ end
164
135
 
165
- UNIX_MODE_TYPES = {
166
- r: 00444,
167
- w: 00222,
168
- x: 00111,
169
- }.freeze
136
+ def path
137
+ if symlink? && @follow_symlink
138
+ link_path
139
+ else
140
+ @path
141
+ end
142
+ end
170
143
  end
171
144
  end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+
3
+ module Train
4
+ class File
5
+ class Local < Train::File
6
+ %w{
7
+ exist? file? socket? directory? symlink? pipe? size basename
8
+ }.each do |m|
9
+ define_method m.to_sym do
10
+ ::File.method(m.to_sym).call(@path)
11
+ end
12
+ end
13
+
14
+ def content
15
+ @content ||= ::File.read(@path, encoding: 'UTF-8')
16
+ rescue StandardError => _
17
+ nil
18
+ end
19
+
20
+ def link_path
21
+ return nil unless symlink?
22
+ begin
23
+ @link_path ||= ::File.realpath(@path)
24
+ rescue Errno::ELOOP => _
25
+ # Leave it blank on symbolic loop, same as readlink
26
+ @link_path = ''
27
+ end
28
+ end
29
+
30
+ def block_device?
31
+ ::File.blockdev?(@path)
32
+ end
33
+
34
+ def character_device?
35
+ ::File.chardev?(@path)
36
+ end
37
+
38
+ def type
39
+ case ::File.ftype(@path)
40
+ when 'blockSpecial'
41
+ :block_device
42
+ when 'characterSpecial'
43
+ :character_device
44
+ when 'link'
45
+ :symlink
46
+ when 'fifo'
47
+ :pipe
48
+ else
49
+ ::File.ftype(@path).to_sym
50
+ end
51
+ end
52
+
53
+ %w{
54
+ mode owner group uid gid mtime selinux_label
55
+ }.each do |field|
56
+ define_method field.to_sym do
57
+ stat[field.to_sym]
58
+ end
59
+ end
60
+
61
+ def mode?(sth)
62
+ mode == sth
63
+ end
64
+
65
+ def linked_to?(dst)
66
+ link_path == dst
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+
3
+ require 'shellwords'
4
+ require 'train/extras/stat'
5
+
6
+ module Train
7
+ class File
8
+ class Local
9
+ class Unix < Train::File::Local
10
+ def sanitize_filename(path)
11
+ @spath = Shellwords.escape(path) || @path
12
+ end
13
+
14
+ def stat
15
+ return @stat if defined?(@stat)
16
+
17
+ begin
18
+ file_stat =
19
+ if @follow_symlink
20
+ ::File.stat(@path)
21
+ else
22
+ ::File.lstat(@path)
23
+ end
24
+ rescue StandardError => _err
25
+ return @stat = {}
26
+ end
27
+
28
+ @stat = {
29
+ type: Train::Extras::Stat.find_type(file_stat.mode),
30
+ mode: file_stat.mode & 07777,
31
+ mtime: file_stat.mtime.to_i,
32
+ size: file_stat.size,
33
+ owner: pw_username(file_stat.uid),
34
+ uid: file_stat.uid,
35
+ group: pw_groupname(file_stat.gid),
36
+ gid: file_stat.gid,
37
+ }
38
+
39
+ lstat = @follow_symlink ? ' -L' : ''
40
+ res = @backend.run_command("stat#{lstat} #{@spath} 2>/dev/null --printf '%C'")
41
+ if res.exit_status == 0 && !res.stdout.empty? && res.stdout != '?'
42
+ @stat[:selinux_label] = res.stdout.strip
43
+ end
44
+
45
+ @stat
46
+ end
47
+
48
+ def mounted
49
+ @mounted ||=
50
+ @backend.run_command("mount | grep -- ' on #{@spath} '")
51
+ end
52
+
53
+ def mounted?
54
+ !mounted.nil? && !mounted.stdout.nil? && !mounted.stdout.empty?
55
+ end
56
+
57
+ def grouped_into?(sth)
58
+ group == sth
59
+ end
60
+
61
+ private
62
+
63
+ def pw_username(uid)
64
+ Etc.getpwuid(uid).name
65
+ rescue ArgumentError => _
66
+ nil
67
+ end
68
+
69
+ def pw_groupname(gid)
70
+ Etc.getgrgid(gid).name
71
+ rescue ArgumentError => _
72
+ nil
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+
3
+ module Train
4
+ class File
5
+ class Local
6
+ class Windows < Train::File::Local
7
+ # Ensures we do not use invalid characters for file names
8
+ # @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions
9
+ def sanitize_filename(path)
10
+ return if path.nil?
11
+ # we do not filter :, backslash and forward slash, since they are part of the path
12
+ @spath = path.gsub(/[<>"|?*]/, '')
13
+ end
14
+
15
+ def product_version
16
+ @product_version ||= @backend.run_command(
17
+ "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"#{@spath}\").ProductVersion").stdout.chomp
18
+ end
19
+
20
+ def file_version
21
+ @file_version ||= @backend.run_command(
22
+ "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"#{@spath}\").FileVersion").stdout.chomp
23
+ end
24
+
25
+ def owner
26
+ owner = @backend.run_command(
27
+ "Get-Acl \"#{@spath}\" | select -expand Owner").stdout.strip
28
+ return if owner.empty?
29
+ owner
30
+ end
31
+
32
+ def stat
33
+ return @stat if defined?(@stat)
34
+
35
+ begin
36
+ file_stat =
37
+ if @follow_symlink
38
+ ::File.stat(@path)
39
+ else
40
+ ::File.lstat(@path)
41
+ end
42
+ rescue StandardError => _err
43
+ return @stat = {}
44
+ end
45
+
46
+ @stat = {
47
+ type: type,
48
+ mode: file_stat.mode,
49
+ mtime: file_stat.mtime.to_i,
50
+ size: file_stat.size,
51
+ owner: owner,
52
+ uid: file_stat.uid,
53
+ group: nil,
54
+ gid: file_stat.gid,
55
+ selinux_label: nil,
56
+ }
57
+
58
+ @stat
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end