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
@@ -1,15 +1,15 @@
1
- # encoding: utf-8
2
1
  require 'helper'
2
+ require 'train/transports/local'
3
+ require 'train/file/remote/linux'
3
4
  require 'train/transports/mock'
4
- require 'train/extras'
5
5
 
6
- describe 'file common' do
7
- let(:cls) { Train::Extras::LinuxFile }
6
+ describe Train::File::Remote::Linux do
7
+ let(:cls) { Train::File::Remote::Linux }
8
8
  let(:backend) {
9
9
  backend = Train::Transports::Mock.new.connection
10
10
  backend.mock_os({ family: 'linux' })
11
11
  backend
12
- }
12
+ }
13
13
 
14
14
  def mock_stat(args, out, err = '', code = 0)
15
15
  backend.mock_command(
@@ -39,7 +39,7 @@ describe 'file common' do
39
39
  it 'reads file contents' do
40
40
  backend.mock_command('cat path || echo -n', '')
41
41
  mock_stat('-L path', '', 'some error...', 1)
42
- cls.new(backend, 'path').content.must_equal nil
42
+ cls.new(backend, 'path').content.must_be_nil
43
43
  end
44
44
 
45
45
  it 'checks for file existance' do
@@ -164,4 +164,4 @@ describe 'file common' do
164
164
  f.selinux_label.must_equal 'labels'
165
165
  end
166
166
  end
167
- end
167
+ end
@@ -0,0 +1,44 @@
1
+ require 'helper'
2
+ require 'train/file/remote/unix'
3
+
4
+ describe Train::File::Remote::Unix do
5
+ let(:cls) { Train::File::Remote::Unix }
6
+
7
+ def mockup(stubs)
8
+ Class.new(cls) do
9
+ stubs.each do |k,v|
10
+ define_method k.to_sym do
11
+ v
12
+ end
13
+ end
14
+ end.new(nil, nil, false)
15
+ end
16
+
17
+ describe 'unix_mode_mask' do
18
+ let(:fc) { mockup(type: :file) }
19
+
20
+ it 'check owner mode calculation' do
21
+ fc.unix_mode_mask('owner', 'x').must_equal 0100
22
+ fc.unix_mode_mask('owner', 'w').must_equal 0200
23
+ fc.unix_mode_mask('owner', 'r').must_equal 0400
24
+ end
25
+
26
+ it 'check group mode calculation' do
27
+ fc.unix_mode_mask('group', 'x').must_equal 0010
28
+ fc.unix_mode_mask('group', 'w').must_equal 0020
29
+ fc.unix_mode_mask('group', 'r').must_equal 0040
30
+ end
31
+
32
+ it 'check other mode calculation' do
33
+ fc.unix_mode_mask('other', 'x').must_equal 0001
34
+ fc.unix_mode_mask('other', 'w').must_equal 0002
35
+ fc.unix_mode_mask('other', 'r').must_equal 0004
36
+ end
37
+
38
+ it 'check all mode calculation' do
39
+ fc.unix_mode_mask('all', 'x').must_equal 0111
40
+ fc.unix_mode_mask('all', 'w').must_equal 0222
41
+ fc.unix_mode_mask('all', 'r').must_equal 0444
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,62 @@
1
+ require 'helper'
2
+ require 'train/file/remote'
3
+
4
+ describe Train::File::Remote do
5
+ let(:cls) { Train::File::Remote }
6
+
7
+ def mockup(stubs)
8
+ Class.new(cls) do
9
+ stubs.each do |k,v|
10
+ define_method k.to_sym do
11
+ v
12
+ end
13
+ end
14
+ end.new(nil, nil, false)
15
+ end
16
+
17
+ describe 'basename helper' do
18
+ def fc(path)
19
+ mockup(type: :file, path: path)
20
+ end
21
+
22
+ it 'works with an empty path' do
23
+ fc('').basename.must_equal ''
24
+ end
25
+
26
+ it 'separates a simple path (defaults to unix mode)' do
27
+ fc('/dir/file').basename.must_equal 'file'
28
+ end
29
+
30
+ it 'separates a simple path (Unix mode)' do
31
+ fc('/dir/file').basename(nil, '/').must_equal 'file'
32
+ end
33
+
34
+ it 'separates a simple path (Windows mode)' do
35
+ fc('C:\dir\file').basename(nil, '\\').must_equal 'file'
36
+ end
37
+
38
+ it 'identifies a folder name (Unix mode)' do
39
+ fc('/dir/file/').basename(nil, '/').must_equal 'file'
40
+ end
41
+
42
+ it 'identifies a folder name (Windows mode)' do
43
+ fc('C:\dir\file\\').basename(nil, '\\').must_equal 'file'
44
+ end
45
+
46
+ it 'ignores tailing separators (Unix mode)' do
47
+ fc('/dir/file///').basename(nil, '/').must_equal 'file'
48
+ end
49
+
50
+ it 'ignores tailing separators (Windows mode)' do
51
+ fc('C:\dir\file\\\\\\').basename(nil, '\\').must_equal 'file'
52
+ end
53
+
54
+ it 'doesnt work with backward slashes (Unix mode)' do
55
+ fc('C:\dir\file').basename(nil, '/').must_equal 'C:\\dir\file'
56
+ end
57
+
58
+ it 'doesnt work with forward slashes (Windows mode)' do
59
+ fc('/dir/file').basename(nil, '\\').must_equal '/dir/file'
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,156 @@
1
+ require 'helper'
2
+
3
+ describe Train::File do
4
+ let(:cls) { Train::File }
5
+ let(:new_cls) { cls.new(nil, '/temp/file', false) }
6
+
7
+ def mockup(stubs)
8
+ Class.new(cls) do
9
+ stubs.each do |k,v|
10
+ define_method k.to_sym do
11
+ v
12
+ end
13
+ end
14
+ end.new(nil, nil, false)
15
+ end
16
+
17
+ it 'has the default type of unknown' do
18
+ new_cls.type.must_equal :unknown
19
+ end
20
+
21
+ it 'calculates md5sum from content' do
22
+ content = 'hello world'
23
+ new_cls.stub :content, content do |i|
24
+ i.md5sum.must_equal '5eb63bbbe01eeed093cb22bb8f5acdc3'
25
+ end
26
+ end
27
+
28
+ it 'sets md5sum of nil content to nil' do
29
+ new_cls.stub :content, nil do |i|
30
+ i.md5sum.must_be_nil
31
+ end
32
+ end
33
+
34
+ it 'calculates sha256sum from content' do
35
+ content = 'hello world'
36
+ new_cls.stub :content, content do |i|
37
+ i.sha256sum.must_equal 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
38
+ end
39
+ end
40
+
41
+ it 'sets sha256sum of nil content to nil' do
42
+ new_cls.stub :content, nil do |i|
43
+ i.sha256sum.must_be_nil
44
+ end
45
+ end
46
+
47
+ it 'throws Not implemented error for exist?' do
48
+ # proc { Train.validate_backend({ host: rand }) }.must_raise Train::UserError
49
+ proc { new_cls.exist?}.must_raise NotImplementedError
50
+ end
51
+
52
+ it 'throws Not implemented error for mode' do
53
+ proc { new_cls.mode }.must_raise NotImplementedError
54
+ end
55
+
56
+ it 'throws Not implemented error for owner' do
57
+ proc { new_cls.owner }.must_raise NotImplementedError
58
+ end
59
+
60
+ it 'throws Not implemented error for group' do
61
+ proc { new_cls.group }.must_raise NotImplementedError
62
+ end
63
+
64
+ it 'throws Not implemented error for uid' do
65
+ proc { new_cls.uid }.must_raise NotImplementedError
66
+ end
67
+
68
+ it 'throws Not implemented error for gid' do
69
+ proc { new_cls.gid }.must_raise NotImplementedError
70
+ end
71
+
72
+ it 'throws Not implemented error for content' do
73
+ proc { new_cls.content }.must_raise NotImplementedError
74
+ end
75
+
76
+ it 'throws Not implemented error for mtime' do
77
+ proc { new_cls.mtime }.must_raise NotImplementedError
78
+ end
79
+
80
+ it 'throws Not implemented error for size' do
81
+ proc { new_cls.size }.must_raise NotImplementedError
82
+ end
83
+
84
+ it 'throws Not implemented error for selinux_label' do
85
+ proc { new_cls.selinux_label }.must_raise NotImplementedError
86
+ end
87
+
88
+ it 'return path of file' do
89
+ new_cls.path.must_equal('/temp/file')
90
+ end
91
+
92
+ it 'set product_version to nil' do
93
+ new_cls.product_version.must_be_nil
94
+ end
95
+
96
+ it 'set product_version to nil' do
97
+ new_cls.file_version.must_be_nil
98
+ end
99
+
100
+
101
+ describe 'type' do
102
+ it 'recognized type == file' do
103
+ fc = mockup(type: :file)
104
+ fc.file?.must_equal true
105
+ end
106
+
107
+ it 'recognized type == block_device' do
108
+ fc = mockup(type: :block_device)
109
+ fc.block_device?.must_equal true
110
+ end
111
+
112
+ it 'recognized type == character_device' do
113
+ fc = mockup(type: :character_device)
114
+ fc.character_device?.must_equal true
115
+ end
116
+
117
+ it 'recognized type == socket' do
118
+ fc = mockup(type: :socket)
119
+ fc.socket?.must_equal true
120
+ end
121
+
122
+ it 'recognized type == directory' do
123
+ fc = mockup(type: :directory)
124
+ fc.directory?.must_equal true
125
+ end
126
+
127
+ it 'recognized type == pipe' do
128
+ fc = mockup(type: :pipe)
129
+ fc.pipe?.must_equal true
130
+ end
131
+
132
+ it 'recognized type == symlink' do
133
+ fc = mockup(type: :symlink)
134
+ fc.symlink?.must_equal true
135
+ end
136
+ end
137
+
138
+ describe 'version' do
139
+ it 'recognized wrong version' do
140
+ fc = mockup(product_version: rand, file_version: rand)
141
+ fc.version?(rand).must_equal false
142
+ end
143
+
144
+ it 'recognized product_version' do
145
+ x = rand
146
+ fc = mockup(product_version: x, file_version: rand)
147
+ fc.version?(x).must_equal true
148
+ end
149
+
150
+ it 'recognized file_version' do
151
+ x = rand
152
+ fc = mockup(product_version: rand, file_version: x)
153
+ fc.version?(x).must_equal true
154
+ end
155
+ end
156
+ end
@@ -86,7 +86,7 @@ describe 'v1 Transport Plugin' do
86
86
 
87
87
  it 'default option must not be required' do
88
88
  name, plugin = train_class
89
- plugin.default_options[name][:required].must_equal nil
89
+ plugin.default_options[name][:required].must_be_nil
90
90
  end
91
91
 
92
92
  it 'can include options from another module' do
@@ -94,11 +94,11 @@ describe 'mock transport' do
94
94
 
95
95
  # tests if all fields between the local json and resulting mock file
96
96
  # are equal
97
- JSON = Train.create('local').connection.file(__FILE__).to_json
98
- RES = Train::Transports::Mock::Connection::File.from_json(JSON)
97
+ JSON_DATA = Train.create('local').connection.file(__FILE__).to_json
98
+ RES = Train::Transports::Mock::Connection::File.from_json(JSON_DATA)
99
99
  %w{ content mode owner group }.each do |f|
100
100
  it "can be initialized from json (field #{f})" do
101
- RES.method(f).call.must_equal JSON[f]
101
+ RES.method(f).call.must_equal JSON_DATA[f]
102
102
  end
103
103
  end
104
104
  end
@@ -6,6 +6,7 @@ require 'minitest/autorun'
6
6
  require 'minitest/spec'
7
7
  require 'mocha/setup'
8
8
  require 'train'
9
+ require 'tempfile'
9
10
 
10
11
  describe 'windows local command' do
11
12
  let(:conn) {
@@ -39,6 +40,111 @@ describe 'windows local command' do
39
40
  cmd.stderr.must_equal ''
40
41
  end
41
42
 
43
+ describe 'file' do
44
+ before do
45
+ @temp = Tempfile.new('foo')
46
+ @temp.write("hello world")
47
+ @temp.rewind
48
+ end
49
+
50
+ let(:file) { conn.file(@temp.path) }
51
+
52
+ it 'exists' do
53
+ file.exist?.must_equal(true)
54
+ end
55
+
56
+ it 'is a file' do
57
+ file.file?.must_equal(true)
58
+ end
59
+
60
+ it 'has type :file' do
61
+ file.type.must_equal(:file)
62
+ end
63
+
64
+ it 'has content' do
65
+ file.content.must_equal("hello world")
66
+ end
67
+
68
+ it 'returns basename of file' do
69
+ file_name = ::File.basename(@temp)
70
+ file.basename.must_equal(file_name)
71
+ end
72
+
73
+ it 'has owner name' do
74
+ file.owner.wont_be_nil
75
+ end
76
+
77
+ it 'has no group name' do
78
+ file.group.must_be_nil
79
+ end
80
+
81
+ it 'has no mode' do
82
+ file.mode.wont_be_nil
83
+ end
84
+
85
+ it 'has an md5sum' do
86
+ file.md5sum.wont_be_nil
87
+ end
88
+
89
+ it 'has an sha256sum' do
90
+ file.sha256sum.wont_be_nil
91
+ end
92
+
93
+ it 'has no modified time' do
94
+ file.mtime.wont_be_nil
95
+ end
96
+
97
+ it 'has no size' do
98
+ file.size.wont_be_nil
99
+ end
100
+
101
+ it 'has size 11' do
102
+ size = ::File.size(@temp)
103
+ file.size.must_equal size
104
+ end
105
+
106
+ it 'has no selinux_label handling' do
107
+ file.selinux_label.must_be_nil
108
+ end
109
+
110
+ it 'has product_version' do
111
+ file.product_version.wont_be_nil
112
+ end
113
+
114
+ it 'has file_version' do
115
+ file.file_version.wont_be_nil
116
+ end
117
+
118
+ it 'provides a json representation' do
119
+ j = file.to_json
120
+ j.must_be_kind_of Hash
121
+ j['type'].must_equal :file
122
+ end
123
+
124
+ after do
125
+ @temp.close
126
+ @temp.unlink
127
+ end
128
+ end
129
+
130
+ describe 'file' do
131
+ before do
132
+ @temp = Tempfile.new('foo bar')
133
+ @temp.rewind
134
+ end
135
+
136
+ let(:file) { conn.file(@temp.path) }
137
+
138
+ it 'provides the full path with whitespace for path #{@temp.path}' do
139
+ file.path.must_equal @temp.path
140
+ end
141
+
142
+ after do
143
+ @temp.close
144
+ @temp.unlink
145
+ end
146
+ end
147
+
42
148
  after do
43
149
  # close the connection
44
150
  conn.close
@@ -45,6 +45,131 @@ describe 'windows winrm command' do
45
45
  cmd.stderr.must_equal ''
46
46
  end
47
47
 
48
+
49
+ describe 'file' do
50
+ before do
51
+ @temp = Tempfile.new('foo')
52
+ @temp.write("hello world")
53
+ @temp.rewind
54
+ end
55
+
56
+ let(:file) { conn.file(@temp.path) }
57
+
58
+ it 'exists' do
59
+ file.exist?.must_equal(true)
60
+ end
61
+
62
+ it 'is a file' do
63
+ file.file?.must_equal(true)
64
+ end
65
+
66
+ it 'has type :file' do
67
+ file.type.must_equal(:file)
68
+ end
69
+
70
+ it 'has content' do
71
+ # TODO: this shouldn't include newlines that aren't in the original file
72
+ file.content.must_equal("hello world\r\n")
73
+ end
74
+
75
+ it 'has owner name' do
76
+ file.owner.wont_be_nil
77
+ end
78
+
79
+ it 'has no group name' do
80
+ file.group.must_be_nil
81
+ end
82
+
83
+ it 'has no mode' do
84
+ file.mode.must_be_nil
85
+ end
86
+
87
+ it 'has an md5sum' do
88
+ file.md5sum.wont_be_nil
89
+ end
90
+
91
+ it 'has an sha256sum' do
92
+ file.sha256sum.wont_be_nil
93
+ end
94
+
95
+ it 'has no modified time' do
96
+ file.mtime.must_be_nil
97
+ end
98
+
99
+ it 'has no size' do
100
+ file.size.wont_be_nil
101
+ end
102
+
103
+ it 'has size 11' do
104
+ size = ::File.size(@temp)
105
+ file.size.must_equal size
106
+ end
107
+
108
+ it 'has no selinux_label handling' do
109
+ file.selinux_label.must_be_nil
110
+ end
111
+
112
+ it 'has product_version' do
113
+ file.product_version.wont_be_nil
114
+ end
115
+
116
+ # TODO: This is not failing in manual testing
117
+ # it 'returns basname of file' do
118
+ # basename = ::File.basename(@temp)
119
+ # file.basename.must_equal basename
120
+ # end
121
+
122
+ it 'has file_version' do
123
+ file.file_version.wont_be_nil
124
+ end
125
+
126
+ it 'returns nil for mounted' do
127
+ file.mounted.must_be_nil
128
+ end
129
+
130
+ it 'has no link_path' do
131
+ file.link_path.must_be_nil
132
+ end
133
+
134
+ it 'has no uid' do
135
+ file.uid.must_be_nil
136
+ end
137
+
138
+ it 'has no gid' do
139
+ file.gid.must_be_nil
140
+ end
141
+
142
+ it 'provides a json representation' do
143
+ j = file.to_json
144
+ j.must_be_kind_of Hash
145
+ j['type'].must_equal :file
146
+ end
147
+
148
+ after do
149
+ @temp.close
150
+ @temp.unlink
151
+ end
152
+ end
153
+
154
+ describe 'file' do
155
+ before do
156
+ @temp = Tempfile.new('foo bar')
157
+ @temp.write("hello world")
158
+ @temp.rewind
159
+ end
160
+
161
+ let(:file) { conn.file(@temp.path) }
162
+
163
+ it 'provides the full path with whitespace for path #{@temp.path}' do
164
+ file.path.must_equal @temp.path
165
+ end
166
+
167
+ after do
168
+ @temp.close
169
+ @temp.unlink
170
+ end
171
+ end
172
+
48
173
  after do
49
174
  # close the connection
50
175
  conn.close