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
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