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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -2
- data/lib/train/extras.rb +0 -5
- data/lib/train/extras/os_common.rb +1 -1
- data/lib/train/extras/os_detect_unix.rb +6 -0
- data/lib/train/{extras/file_common.rb → file.rb} +65 -92
- data/lib/train/file/local.rb +70 -0
- data/lib/train/file/local/unix.rb +77 -0
- data/lib/train/file/local/windows.rb +63 -0
- data/lib/train/file/remote.rb +28 -0
- data/lib/train/file/remote/aix.rb +21 -0
- data/lib/train/file/remote/linux.rb +19 -0
- data/lib/train/file/remote/qnx.rb +41 -0
- data/lib/train/file/remote/unix.rb +110 -0
- data/lib/train/file/remote/windows.rb +94 -0
- data/lib/train/plugins/base_connection.rb +2 -1
- data/lib/train/transports/docker.rb +8 -1
- data/lib/train/transports/local.rb +6 -2
- data/lib/train/transports/mock.rb +7 -6
- data/lib/train/transports/ssh.rb +1 -2
- data/lib/train/transports/ssh_connection.rb +24 -4
- data/lib/train/transports/winrm_connection.rb +11 -5
- data/lib/train/version.rb +1 -1
- data/test/integration/tests/path_block_device_test.rb +2 -2
- data/test/integration/tests/path_character_device_test.rb +2 -2
- data/test/integration/tests/path_file_test.rb +2 -2
- data/test/integration/tests/path_folder_test.rb +5 -5
- data/test/integration/tests/path_missing_test.rb +0 -1
- data/test/integration/tests/path_pipe_test.rb +2 -3
- data/test/integration/tests/path_symlink_test.rb +2 -2
- data/test/unit/extras/os_detect_linux_test.rb +3 -3
- data/test/unit/extras/os_detect_windows_test.rb +1 -1
- data/test/unit/file/local/unix_test.rb +112 -0
- data/test/unit/file/local/windows_test.rb +41 -0
- data/test/unit/file/local_test.rb +110 -0
- data/test/unit/{extras/linux_file_test.rb → file/remote/linux_test.rb} +7 -7
- data/test/unit/file/remote/unix_test.rb +44 -0
- data/test/unit/file/remote_test.rb +62 -0
- data/test/unit/file_test.rb +156 -0
- data/test/unit/plugins/transport_test.rb +1 -1
- data/test/unit/transports/mock_test.rb +3 -3
- data/test/windows/local_test.rb +106 -0
- data/test/windows/winrm_test.rb +125 -0
- metadata +26 -16
- data/lib/train/extras/file_aix.rb +0 -20
- data/lib/train/extras/file_linux.rb +0 -16
- data/lib/train/extras/file_unix.rb +0 -79
- data/lib/train/extras/file_windows.rb +0 -100
- data/lib/train/transports/local_file.rb +0 -98
- data/test/unit/extras/file_common_test.rb +0 -180
- data/test/unit/extras/windows_file_test.rb +0 -44
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b82f61f801217ce81fc40bb5ad6a6e73a19da3de
|
4
|
+
data.tar.gz: 25fb11d1d6930ecda79bb5d2e70030ddddcf976b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c752a556c55eadeaec19702a6db9ba3110b17b55418f3301a04d919ae899a3e806ed716ce5239515f33efb203e98d6678a8d0bed0f515a8cf0e4cbf22e1dc9f
|
7
|
+
data.tar.gz: 51098591df48b28d34798dbf729c701f903889e55d63f48a38115aeea0a94d2eca48bcc32bba33b398700574f66db6d7f980aa2e50b1b9fda528edba9b96cba6
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/train/compare/v0.
|
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)
|
data/lib/train/extras.rb
CHANGED
@@ -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
|
-
#
|
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
|
99
|
-
|
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
|
-
|
115
|
-
|
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
|
-
|
119
|
-
|
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
|
128
|
-
|
129
|
-
|
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
|
-
|
108
|
+
def character_device?
|
109
|
+
type.to_s == 'character_device'
|
135
110
|
end
|
136
111
|
|
137
|
-
def
|
138
|
-
|
112
|
+
def pipe?
|
113
|
+
type.to_s == 'pipe'
|
139
114
|
end
|
140
115
|
|
141
|
-
def
|
142
|
-
|
143
|
-
@basename ||= detect_filename(path, sep || '/')
|
116
|
+
def file?
|
117
|
+
type.to_s == 'file'
|
144
118
|
end
|
145
119
|
|
146
|
-
|
120
|
+
def socket?
|
121
|
+
type.to_s == 'socket'
|
122
|
+
end
|
147
123
|
|
148
|
-
|
124
|
+
def directory?
|
125
|
+
type.to_s == 'directory'
|
126
|
+
end
|
149
127
|
|
150
|
-
def
|
151
|
-
|
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
|
-
|
159
|
-
|
160
|
-
|
161
|
-
group: 00070,
|
162
|
-
other: 00007,
|
163
|
-
}.freeze
|
132
|
+
def owned_by?(sth)
|
133
|
+
owner == sth
|
134
|
+
end
|
164
135
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
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
|