train 0.28.0 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
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