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
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.28.0
4
+ version: 0.29.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: 2017-09-25 00:00:00.000000000 Z
11
+ date: 2017-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -151,11 +151,6 @@ files:
151
151
  - lib/train/errors.rb
152
152
  - lib/train/extras.rb
153
153
  - lib/train/extras/command_wrapper.rb
154
- - lib/train/extras/file_aix.rb
155
- - lib/train/extras/file_common.rb
156
- - lib/train/extras/file_linux.rb
157
- - lib/train/extras/file_unix.rb
158
- - lib/train/extras/file_windows.rb
159
154
  - lib/train/extras/linux_lsb.rb
160
155
  - lib/train/extras/os_common.rb
161
156
  - lib/train/extras/os_detect_arista_eos.rb
@@ -167,13 +162,22 @@ files:
167
162
  - lib/train/extras/os_detect_windows.rb
168
163
  - lib/train/extras/stat.rb
169
164
  - lib/train/extras/uname.rb
165
+ - lib/train/file.rb
166
+ - lib/train/file/local.rb
167
+ - lib/train/file/local/unix.rb
168
+ - lib/train/file/local/windows.rb
169
+ - lib/train/file/remote.rb
170
+ - lib/train/file/remote/aix.rb
171
+ - lib/train/file/remote/linux.rb
172
+ - lib/train/file/remote/qnx.rb
173
+ - lib/train/file/remote/unix.rb
174
+ - lib/train/file/remote/windows.rb
170
175
  - lib/train/options.rb
171
176
  - lib/train/plugins.rb
172
177
  - lib/train/plugins/base_connection.rb
173
178
  - lib/train/plugins/transport.rb
174
179
  - lib/train/transports/docker.rb
175
180
  - lib/train/transports/local.rb
176
- - lib/train/transports/local_file.rb
177
181
  - lib/train/transports/local_os.rb
178
182
  - lib/train/transports/mock.rb
179
183
  - lib/train/transports/ssh.rb
@@ -213,19 +217,22 @@ files:
213
217
  - test/integration/tests/path_symlink_test.rb
214
218
  - test/integration/tests/run_command_test.rb
215
219
  - test/unit/extras/command_wrapper_test.rb
216
- - test/unit/extras/file_common_test.rb
217
- - test/unit/extras/linux_file_test.rb
218
220
  - test/unit/extras/os_common_test.rb
219
221
  - test/unit/extras/os_detect_linux_test.rb
220
222
  - test/unit/extras/os_detect_windows_test.rb
221
223
  - test/unit/extras/stat_test.rb
222
- - test/unit/extras/windows_file_test.rb
224
+ - test/unit/file/local/unix_test.rb
225
+ - test/unit/file/local/windows_test.rb
226
+ - test/unit/file/local_test.rb
227
+ - test/unit/file/remote/linux_test.rb
228
+ - test/unit/file/remote/unix_test.rb
229
+ - test/unit/file/remote_test.rb
230
+ - test/unit/file_test.rb
223
231
  - test/unit/helper.rb
224
232
  - test/unit/plugins/connection_test.rb
225
233
  - test/unit/plugins/transport_test.rb
226
234
  - test/unit/plugins_test.rb
227
235
  - test/unit/train_test.rb
228
- - test/unit/transports/local_file_test.rb
229
236
  - test/unit/transports/local_test.rb
230
237
  - test/unit/transports/mock_test.rb
231
238
  - test/unit/transports/ssh_test.rb
@@ -290,19 +297,22 @@ test_files:
290
297
  - test/integration/tests/path_symlink_test.rb
291
298
  - test/integration/tests/run_command_test.rb
292
299
  - test/unit/extras/command_wrapper_test.rb
293
- - test/unit/extras/file_common_test.rb
294
- - test/unit/extras/linux_file_test.rb
295
300
  - test/unit/extras/os_common_test.rb
296
301
  - test/unit/extras/os_detect_linux_test.rb
297
302
  - test/unit/extras/os_detect_windows_test.rb
298
303
  - test/unit/extras/stat_test.rb
299
- - test/unit/extras/windows_file_test.rb
304
+ - test/unit/file/local/unix_test.rb
305
+ - test/unit/file/local/windows_test.rb
306
+ - test/unit/file/local_test.rb
307
+ - test/unit/file/remote/linux_test.rb
308
+ - test/unit/file/remote/unix_test.rb
309
+ - test/unit/file/remote_test.rb
310
+ - test/unit/file_test.rb
300
311
  - test/unit/helper.rb
301
312
  - test/unit/plugins/connection_test.rb
302
313
  - test/unit/plugins/transport_test.rb
303
314
  - test/unit/plugins_test.rb
304
315
  - test/unit/train_test.rb
305
- - test/unit/transports/local_file_test.rb
306
316
  - test/unit/transports/local_test.rb
307
317
  - test/unit/transports/mock_test.rb
308
318
  - test/unit/transports/ssh_test.rb
@@ -1,20 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'shellwords'
4
- require 'train/extras/stat'
5
-
6
- module Train::Extras
7
- class AixFile < UnixFile
8
- def link_path
9
- return nil unless symlink?
10
- @link_path ||=
11
- @backend.run_command("perl -e 'print readlink shift' #{@spath}")
12
- .stdout.chomp
13
- end
14
-
15
- def mounted
16
- @mounted ||=
17
- @backend.run_command("lsfs -c #{@spath}")
18
- end
19
- end
20
- end
@@ -1,16 +0,0 @@
1
- # encoding: utf-8
2
- # author: Dominik Richter
3
- # author: Christoph Hartmann
4
-
5
- module Train::Extras
6
- class LinuxFile < UnixFile
7
- def content
8
- return @content if defined?(@content)
9
- @content = @backend.run_command(
10
- "cat #{@spath} || echo -n").stdout
11
- return @content unless @content.empty?
12
- @content = nil if directory? or size.nil? or size > 0
13
- @content
14
- end
15
- end
16
- end
@@ -1,79 +0,0 @@
1
- # encoding: utf-8
2
- # author: Dominik Richter
3
- # author: Christoph Hartmann
4
-
5
- require 'shellwords'
6
- require 'train/extras/stat'
7
-
8
- module Train::Extras
9
- class UnixFile < FileCommon
10
- attr_reader :path
11
- def initialize(backend, path, follow_symlink = true)
12
- super(backend, path, follow_symlink)
13
- @spath = Shellwords.escape(@path)
14
- end
15
-
16
- def content
17
- @content ||= case
18
- when !exist?, directory?
19
- nil
20
- when size.nil?, size == 0
21
- ''
22
- else
23
- @backend.run_command("cat #{@spath}").stdout || ''
24
- end
25
- end
26
-
27
- def exist?
28
- @exist ||= (
29
- f = @follow_symlink ? '' : " || test -L #{@spath}"
30
- @backend.run_command("test -e #{@spath}"+f)
31
- .exit_status == 0
32
- )
33
- end
34
-
35
- def path
36
- return @path unless @follow_symlink && symlink?
37
- @link_path ||= read_target_path
38
- end
39
-
40
- def mounted
41
- @mounted ||=
42
- @backend.run_command("mount | grep -- ' on #{@spath} '")
43
- end
44
-
45
- %w{
46
- type mode owner group uid gid mtime size selinux_label
47
- }.each do |field|
48
- define_method field.to_sym do
49
- stat[field.to_sym]
50
- end
51
- end
52
-
53
- def product_version
54
- nil
55
- end
56
-
57
- def file_version
58
- nil
59
- end
60
-
61
- def stat
62
- return @stat if defined?(@stat)
63
- @stat = Train::Extras::Stat.stat(@spath, @backend, @follow_symlink)
64
- end
65
-
66
- private
67
-
68
- # Returns full path of a symlink target(real dest) or '' on symlink loop
69
- def read_target_path
70
- full_path = @backend.run_command("readlink -n #{@spath} -f").stdout
71
- # Needed for some OSes like OSX that returns relative path
72
- # when the link and target are in the same directory
73
- if !full_path.start_with?('/') && full_path != ''
74
- full_path = File.expand_path("../#{full_path}", @spath)
75
- end
76
- full_path
77
- end
78
- end
79
- end
@@ -1,100 +0,0 @@
1
- # encoding: utf-8
2
- # author: Dominik Richter
3
- # author: Christoph Hartmann
4
-
5
- require 'shellwords'
6
- require 'train/extras/stat'
7
-
8
- # PS C:\Users\Administrator> Get-Item -Path C:\test.txt | Select-Object -Property BaseName, FullName, IsReadOnly, Exists,
9
- # LinkType, Mode, VersionInfo, Owner, Archive, Hidden, ReadOnly, System | ConvertTo-Json
10
-
11
- module Train::Extras
12
- class WindowsFile < FileCommon
13
- attr_reader :path
14
- def initialize(backend, path, follow_symlink = false)
15
- super(backend, path, follow_symlink)
16
- @spath = sanitize_filename(@path)
17
- end
18
-
19
- def basename(suffix = nil, sep = '\\')
20
- super(suffix, sep)
21
- end
22
-
23
- # Ensures we do not use invalid characters for file names
24
- # @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#naming_conventions
25
- def sanitize_filename(filename)
26
- return if filename.nil?
27
- # we do not filter :, backslash and forward slash, since they are part of the path
28
- filename.gsub(/[<>"|?*]/, '')
29
- end
30
-
31
- def content
32
- return @content if defined?(@content)
33
- @content = @backend.run_command(
34
- "Get-Content(\"#{@spath}\") | Out-String").stdout
35
- return @content unless @content.empty?
36
- @content = nil if directory? # or size.nil? or size > 0
37
- @content
38
- end
39
-
40
- def exist?
41
- return @exist if defined?(@exist)
42
- @exist = @backend.run_command(
43
- "(Test-Path -Path \"#{@spath}\").ToString()").stdout.chomp == 'True'
44
- end
45
-
46
- def link_path
47
- nil
48
- end
49
-
50
- def mounted
51
- nil
52
- end
53
-
54
- def owner
55
- owner = @backend.run_command(
56
- "Get-Acl '#{@spath}' | select -expand Owner").stdout.strip
57
- return if owner.empty?
58
- owner
59
- end
60
-
61
- def type
62
- if attributes.include?('Archive')
63
- return :file
64
- elsif attributes.include?('Directory')
65
- return :directory
66
- end
67
- :unknown
68
- end
69
-
70
- %w{
71
- mode group uid gid mtime size selinux_label
72
- }.each do |field|
73
- define_method field.to_sym do
74
- nil
75
- end
76
- end
77
-
78
- def product_version
79
- @product_version ||= @backend.run_command(
80
- "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"#{@spath}\").ProductVersion").stdout.chomp
81
- end
82
-
83
- def file_version
84
- @file_version ||= @backend.run_command(
85
- "[System.Diagnostics.FileVersionInfo]::GetVersionInfo(\"#{@spath}\").FileVersion").stdout.chomp
86
- end
87
-
88
- def stat
89
- nil
90
- end
91
-
92
- private
93
-
94
- def attributes
95
- return @attributes if defined?(@attributes)
96
- @attributes = @backend.run_command(
97
- "(Get-ItemProperty -Path \"#{@spath}\").attributes.ToString()").stdout.chomp.split(/\s*,\s*/)
98
- end
99
- end
100
- end
@@ -1,98 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # author: Dominik Richter
4
- # author: Christoph Hartmann
5
-
6
- require 'train/extras'
7
-
8
- class Train::Transports::Local::Connection
9
- class File < Train::Extras::LinuxFile
10
- def content
11
- @content ||= ::File.read(@path, encoding: 'UTF-8')
12
- rescue StandardError => _
13
- nil
14
- end
15
-
16
- %w{
17
- exist? file? socket? directory? symlink? pipe?
18
- }.each do |m|
19
- define_method m.to_sym do
20
- ::File.method(m.to_sym).call(@path)
21
- end
22
- end
23
-
24
- def path
25
- if symlink? && @follow_symlink
26
- link_path
27
- else
28
- @path
29
- end
30
- end
31
-
32
- def link_path
33
- return nil unless symlink?
34
- begin
35
- @link_path ||= ::File.realpath(@path)
36
- rescue Errno::ELOOP => _
37
- # Leave it blank on symbolic loop, same as readlink
38
- @link_path = ''
39
- end
40
- end
41
-
42
- def block_device?
43
- ::File.blockdev?(@path)
44
- end
45
-
46
- def character_device?
47
- ::File.chardev?(@path)
48
- end
49
-
50
- private
51
-
52
- def pw_username(uid)
53
- Etc.getpwuid(uid).name
54
- rescue ArgumentError => _
55
- nil
56
- end
57
-
58
- def pw_groupname(gid)
59
- Etc.getgrgid(gid).name
60
- rescue ArgumentError => _
61
- nil
62
- end
63
-
64
- def stat
65
- return @stat if defined? @stat
66
-
67
- begin
68
- file_stat =
69
- if @follow_symlink
70
- ::File.stat(@path)
71
- else
72
- ::File.lstat(@path)
73
- end
74
- rescue StandardError => _err
75
- return @stat = {}
76
- end
77
-
78
- @stat = {
79
- type: Train::Extras::Stat.find_type(file_stat.mode),
80
- mode: file_stat.mode & 07777,
81
- mtime: file_stat.mtime.to_i,
82
- size: file_stat.size,
83
- owner: pw_username(file_stat.uid),
84
- uid: file_stat.uid,
85
- group: pw_groupname(file_stat.gid),
86
- gid: file_stat.gid,
87
- }
88
-
89
- lstat = @follow_symlink ? ' -L' : ''
90
- res = @backend.run_command("stat#{lstat} #{@spath} 2>/dev/null --printf '%C'")
91
- if res.exit_status == 0 && !res.stdout.empty? && res.stdout != '?'
92
- @stat[:selinux_label] = res.stdout.strip
93
- end
94
-
95
- @stat
96
- end
97
- end
98
- end
@@ -1,180 +0,0 @@
1
- # encoding: utf-8
2
- require 'helper'
3
- require 'securerandom'
4
- require 'train/extras/file_common'
5
-
6
- describe 'file common' do
7
- let(:cls) { Train::Extras::FileCommon }
8
- let(:new_cls) { cls.new(nil, nil, false) }
9
-
10
- def mockup(stubs)
11
- Class.new(cls) do
12
- stubs.each do |k,v|
13
- define_method k.to_sym do
14
- v
15
- end
16
- end
17
- end.new(nil, nil, false)
18
- end
19
-
20
- it 'has the default type of unknown' do
21
- new_cls.type.must_equal :unknown
22
- end
23
-
24
- it 'calculates md5sum from content' do
25
- content = 'hello world'
26
- new_cls.stub :content, content do |i|
27
- i.md5sum.must_equal '5eb63bbbe01eeed093cb22bb8f5acdc3'
28
- end
29
- end
30
-
31
- it 'sets md5sum of nil content to nil' do
32
- new_cls.stub :content, nil do |i|
33
- i.md5sum.must_be_nil
34
- end
35
- end
36
-
37
- it 'calculates md5sum from content' do
38
- content = 'hello world'
39
- new_cls.stub :content, content do |i|
40
- i.sha256sum.must_equal 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
41
- end
42
- end
43
-
44
- it 'sets sha256sum of nil content to nil' do
45
- new_cls.stub :content, nil do |i|
46
- i.sha256sum.must_be_nil
47
- end
48
- end
49
-
50
- describe 'type' do
51
- it 'recognized type == file' do
52
- fc = mockup(type: :file)
53
- fc.file?.must_equal true
54
- end
55
-
56
- it 'recognized type == block_device' do
57
- fc = mockup(type: :block_device)
58
- fc.block_device?.must_equal true
59
- end
60
-
61
- it 'recognized type == character_device' do
62
- fc = mockup(type: :character_device)
63
- fc.character_device?.must_equal true
64
- end
65
-
66
- it 'recognized type == socket' do
67
- fc = mockup(type: :socket)
68
- fc.socket?.must_equal true
69
- end
70
-
71
- it 'recognized type == directory' do
72
- fc = mockup(type: :directory)
73
- fc.directory?.must_equal true
74
- end
75
-
76
- it 'recognized type == pipe' do
77
- fc = mockup(type: :pipe)
78
- fc.pipe?.must_equal true
79
- end
80
-
81
- it 'recognized type == symlink' do
82
- fc = mockup(type: :symlink)
83
- fc.symlink?.must_equal true
84
- end
85
- end
86
-
87
- describe 'version' do
88
- it 'recognized wrong version' do
89
- fc = mockup(product_version: rand, file_version: rand)
90
- fc.version?(rand).must_equal false
91
- end
92
-
93
- it 'recognized product_version' do
94
- x = rand
95
- fc = mockup(product_version: x, file_version: rand)
96
- fc.version?(x).must_equal true
97
- end
98
-
99
- it 'recognized file_version' do
100
- x = rand
101
- fc = mockup(product_version: rand, file_version: x)
102
- fc.version?(x).must_equal true
103
- end
104
- end
105
-
106
- describe 'unix_mode_mask' do
107
-
108
- let(:fc) { mockup(type: :file) }
109
-
110
- it 'check owner mode calculation' do
111
- fc.unix_mode_mask('owner', 'x').must_equal 0100
112
- fc.unix_mode_mask('owner', 'w').must_equal 0200
113
- fc.unix_mode_mask('owner', 'r').must_equal 0400
114
- end
115
-
116
- it 'check group mode calculation' do
117
- fc.unix_mode_mask('group', 'x').must_equal 0010
118
- fc.unix_mode_mask('group', 'w').must_equal 0020
119
- fc.unix_mode_mask('group', 'r').must_equal 0040
120
- end
121
-
122
- it 'check other mode calculation' do
123
- fc.unix_mode_mask('other', 'x').must_equal 0001
124
- fc.unix_mode_mask('other', 'w').must_equal 0002
125
- fc.unix_mode_mask('other', 'r').must_equal 0004
126
- end
127
-
128
- it 'check all mode calculation' do
129
- fc.unix_mode_mask('all', 'x').must_equal 0111
130
- fc.unix_mode_mask('all', 'w').must_equal 0222
131
- fc.unix_mode_mask('all', 'r').must_equal 0444
132
- end
133
- end
134
-
135
- describe 'basename helper' do
136
- def fc(path)
137
- mockup(type: :file, path: path)
138
- end
139
-
140
- it 'works with an empty path' do
141
- fc('').basename.must_equal ''
142
- end
143
-
144
- it 'separates a simple path (defaults to unix mode)' do
145
- fc('/dir/file').basename.must_equal 'file'
146
- end
147
-
148
- it 'separates a simple path (Unix mode)' do
149
- fc('/dir/file').basename(nil, '/').must_equal 'file'
150
- end
151
-
152
- it 'separates a simple path (Windows mode)' do
153
- fc('C:\dir\file').basename(nil, '\\').must_equal 'file'
154
- end
155
-
156
- it 'identifies a folder name (Unix mode)' do
157
- fc('/dir/file/').basename(nil, '/').must_equal 'file'
158
- end
159
-
160
- it 'identifies a folder name (Windows mode)' do
161
- fc('C:\dir\file\\').basename(nil, '\\').must_equal 'file'
162
- end
163
-
164
- it 'ignores tailing separators (Unix mode)' do
165
- fc('/dir/file///').basename(nil, '/').must_equal 'file'
166
- end
167
-
168
- it 'ignores tailing separators (Windows mode)' do
169
- fc('C:\dir\file\\\\\\').basename(nil, '\\').must_equal 'file'
170
- end
171
-
172
- it 'doesnt work with backward slashes (Unix mode)' do
173
- fc('C:\dir\file').basename(nil, '/').must_equal 'C:\\dir\file'
174
- end
175
-
176
- it 'doesnt work with forward slashes (Windows mode)' do
177
- fc('/dir/file').basename(nil, '\\').must_equal '/dir/file'
178
- end
179
- end
180
- end