train 0.29.2 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -2
- data/lib/train.rb +1 -0
- data/lib/train/errors.rb +6 -0
- data/lib/train/extras.rb +0 -1
- data/lib/train/platforms.rb +82 -0
- data/lib/train/platforms/common.rb +34 -0
- data/lib/train/platforms/detect.rb +12 -0
- data/lib/train/platforms/detect/helpers/os_common.rb +56 -0
- data/lib/train/platforms/detect/helpers/os_linux.rb +75 -0
- data/lib/train/{extras/os_detect_windows.rb → platforms/detect/helpers/os_windows.rb} +3 -10
- data/lib/train/platforms/detect/scanner.rb +84 -0
- data/lib/train/platforms/detect/specifications/os.rb +480 -0
- data/lib/train/platforms/family.rb +26 -0
- data/lib/train/platforms/platform.rb +80 -0
- data/lib/train/plugins/base_connection.rb +75 -27
- data/lib/train/transports/docker.rb +17 -28
- data/lib/train/transports/local.rb +21 -22
- data/lib/train/transports/mock.rb +44 -30
- data/lib/train/transports/ssh_connection.rb +55 -67
- data/lib/train/transports/winrm_connection.rb +16 -26
- data/lib/train/version.rb +1 -1
- data/test/unit/file/remote/linux_test.rb +2 -2
- data/test/unit/platforms/detect/os_common_test.rb +85 -0
- data/test/unit/platforms/detect/os_linux_test.rb +124 -0
- data/test/unit/{extras/os_detect_windows_test.rb → platforms/detect/os_windows_test.rb} +5 -2
- data/test/unit/platforms/detect/scanner_test.rb +61 -0
- data/test/unit/platforms/family_test.rb +32 -0
- data/test/unit/platforms/os_detect_test.rb +175 -0
- data/test/unit/{extras/os_common_test.rb → platforms/platform_test.rb} +103 -18
- data/test/unit/platforms/platforms_test.rb +42 -0
- data/test/unit/plugins/connection_test.rb +106 -8
- data/test/unit/transports/local_test.rb +20 -15
- data/test/unit/transports/mock_test.rb +16 -6
- data/test/unit/transports/ssh_test.rb +17 -15
- metadata +28 -19
- data/lib/train/extras/linux_lsb.rb +0 -60
- data/lib/train/extras/os_common.rb +0 -151
- data/lib/train/extras/os_detect_arista_eos.rb +0 -34
- data/lib/train/extras/os_detect_darwin.rb +0 -40
- data/lib/train/extras/os_detect_esx.rb +0 -22
- data/lib/train/extras/os_detect_linux.rb +0 -164
- data/lib/train/extras/os_detect_openvms.rb +0 -29
- data/lib/train/extras/os_detect_unix.rb +0 -106
- data/lib/train/extras/uname.rb +0 -28
- data/lib/train/transports/local_os.rb +0 -51
- data/test/unit/extras/os_detect_linux_test.rb +0 -230
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e4971c8f699dbb772e9eb5532fa2de1771de4a5
|
4
|
+
data.tar.gz: 40bf72dd2c53b33379c256b4a4f4acc42dc46efd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c5fdd0a5d53e68d3eb928d5e9ddcbcaea5a8c3fa39b57d7aa3a20f7135f4436d78e334e4d93b3ce1e8f2fd2a3310462d10ae4099899372bd4f4fbd6309af4e4
|
7
|
+
data.tar.gz: db6f8f5c82f459a9f78c60cf758aaad8c4877e5adee714add3e060e5328c85a4275ef3502aae0525d80a49b0100b92fea2345f5f493fddf2ecc766954dae9c44
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,34 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/train/compare/v0.29.
|
3
|
+
## [0.30.0](https://github.com/chef/train/tree/0.30.0) (2017-12-04)
|
4
|
+
[Full Changelog](https://github.com/chef/train/compare/v0.29.2...0.30.0)
|
5
5
|
|
6
6
|
**Merged pull requests:**
|
7
7
|
|
8
|
+
- Change the mock transport name to be 'mock' [\#221](https://github.com/chef/train/pull/221) ([jquick](https://github.com/jquick))
|
9
|
+
- Enable caching on connections [\#214](https://github.com/chef/train/pull/214) ([jquick](https://github.com/jquick))
|
10
|
+
|
11
|
+
## [v0.29.2](https://github.com/chef/train/tree/v0.29.2) (2017-11-21)
|
12
|
+
[Full Changelog](https://github.com/chef/train/compare/v0.29.1...v0.29.2)
|
13
|
+
|
14
|
+
**Fixed bugs:**
|
15
|
+
|
16
|
+
- Add unix\_mode\_mask method to Train::File::Local::Unix [\#215](https://github.com/chef/train/pull/215) ([adamleff](https://github.com/adamleff))
|
17
|
+
|
18
|
+
**Merged pull requests:**
|
19
|
+
|
20
|
+
- Fix regressions in 0.29.1 [\#219](https://github.com/chef/train/pull/219) ([adamleff](https://github.com/adamleff))
|
21
|
+
- Use the sanitized file path for remote linux files [\#218](https://github.com/chef/train/pull/218) ([RoboticCheese](https://github.com/RoboticCheese))
|
22
|
+
- Remove bundler install during Appveyor tests [\#217](https://github.com/chef/train/pull/217) ([adamleff](https://github.com/adamleff))
|
23
|
+
- Fix inspec mock tests [\#216](https://github.com/chef/train/pull/216) ([jquick](https://github.com/jquick))
|
24
|
+
- Platform framework and detect DSL [\#209](https://github.com/chef/train/pull/209) ([jquick](https://github.com/jquick))
|
25
|
+
|
26
|
+
## [v0.29.1](https://github.com/chef/train/tree/v0.29.1) (2017-11-13)
|
27
|
+
[Full Changelog](https://github.com/chef/train/compare/v0.29.0...v0.29.1)
|
28
|
+
|
29
|
+
**Merged pull requests:**
|
30
|
+
|
31
|
+
- Release 0.29.1 [\#213](https://github.com/chef/train/pull/213) ([adamleff](https://github.com/adamleff))
|
8
32
|
- Allow for a nil value when mocking OS [\#212](https://github.com/chef/train/pull/212) ([adamleff](https://github.com/adamleff))
|
9
33
|
- Ensure a `mounted?` method exists for all File classes, including Mock [\#211](https://github.com/chef/train/pull/211) ([adamleff](https://github.com/adamleff))
|
10
34
|
|
data/lib/train.rb
CHANGED
data/lib/train/errors.rb
CHANGED
@@ -20,4 +20,10 @@ module Train
|
|
20
20
|
# Base exception class for all exceptions that are caused by other failures
|
21
21
|
# in the transport layer.
|
22
22
|
class TransportError < ::StandardError; end
|
23
|
+
|
24
|
+
# Exception for when no platform can be detected.
|
25
|
+
class PlatformDetectionFailed < ::StandardError; end
|
26
|
+
|
27
|
+
# Exception for when a invalid cache type is passed.
|
28
|
+
class UnknownCacheType < ::StandardError; end
|
23
29
|
end
|
data/lib/train/extras.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'train/platforms/common'
|
4
|
+
require 'train/platforms/family'
|
5
|
+
require 'train/platforms/platform'
|
6
|
+
require 'train/platforms/detect'
|
7
|
+
require 'train/platforms/detect/scanner'
|
8
|
+
require 'train/platforms/detect/specifications/os'
|
9
|
+
|
10
|
+
module Train::Platforms
|
11
|
+
class << self
|
12
|
+
# Retrieve the current platform list
|
13
|
+
#
|
14
|
+
# @return [Hash] map with platform names and their objects
|
15
|
+
def list
|
16
|
+
@list ||= {}
|
17
|
+
end
|
18
|
+
|
19
|
+
# Retrieve the current family list
|
20
|
+
#
|
21
|
+
# @return [Hash] map with family names and their objects
|
22
|
+
def families
|
23
|
+
@families ||= {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create or update a platform
|
28
|
+
#
|
29
|
+
# @return Train::Platform
|
30
|
+
def self.name(name, condition = {})
|
31
|
+
# Check the list to see if one is already created
|
32
|
+
plat = list[name]
|
33
|
+
unless plat.nil?
|
34
|
+
# Pass the condition incase we are adding a family relationship
|
35
|
+
plat.condition = condition unless condition.nil?
|
36
|
+
return plat
|
37
|
+
end
|
38
|
+
|
39
|
+
Train::Platforms::Platform.new(name, condition)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create or update a family
|
43
|
+
#
|
44
|
+
# @return Train::Platforms::Family
|
45
|
+
def self.family(name, condition = {})
|
46
|
+
# Check the families to see if one is already created
|
47
|
+
family = families[name]
|
48
|
+
unless family.nil?
|
49
|
+
# Pass the condition incase we are adding a family relationship
|
50
|
+
family.condition = condition unless condition.nil?
|
51
|
+
return family
|
52
|
+
end
|
53
|
+
|
54
|
+
Train::Platforms::Family.new(name, condition)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Find the families or top level platforms
|
58
|
+
#
|
59
|
+
# @return [Hash] with top level family and platforms
|
60
|
+
def self.top_platforms
|
61
|
+
top_platforms = list.select { |_key, value| value.families.empty? }
|
62
|
+
top_platforms.merge!(families.select { |_key, value| value.families.empty? })
|
63
|
+
top_platforms
|
64
|
+
end
|
65
|
+
|
66
|
+
# List all platforms and families in a readable output
|
67
|
+
def self.list_all
|
68
|
+
top_platforms = self.top_platforms
|
69
|
+
top_platforms.each_value do |platform|
|
70
|
+
puts platform.title
|
71
|
+
print_children(platform) if defined?(platform.children)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.print_children(parent, pad = 2)
|
76
|
+
parent.children.each do |key, value|
|
77
|
+
obj = key
|
78
|
+
puts "#{' ' * pad}-> #{obj.title}#{value unless value.empty?}"
|
79
|
+
print_children(obj, pad + 2) if defined?(obj.children) && !obj.children.nil?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Train::Platforms
|
4
|
+
module Common
|
5
|
+
# Add a family connection. This will create a family
|
6
|
+
# if it does not exist and add a child relationship.
|
7
|
+
def in_family(family)
|
8
|
+
if self.class == Train::Platforms::Family && @name == family
|
9
|
+
fail "Unable to add family #{@name} to itself: '#{@name}.in_family(#{family})'"
|
10
|
+
end
|
11
|
+
|
12
|
+
# add family to the family list
|
13
|
+
family = Train::Platforms.family(family)
|
14
|
+
family.children[self] = @condition
|
15
|
+
|
16
|
+
@families[family] = @condition
|
17
|
+
@condition = nil
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def detect(&block)
|
22
|
+
if block_given?
|
23
|
+
@detect = block
|
24
|
+
self
|
25
|
+
elsif @detect.nil?
|
26
|
+
# we are returning a block that just returns false here
|
27
|
+
# to skip the family/platform evaluation if detect is not set
|
28
|
+
->(_) { false }
|
29
|
+
else
|
30
|
+
@detect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'train/platforms/detect/helpers/os_linux'
|
4
|
+
require 'train/platforms/detect/helpers/os_windows'
|
5
|
+
require 'rbconfig'
|
6
|
+
|
7
|
+
module Train::Platforms::Detect::Helpers
|
8
|
+
module OSCommon
|
9
|
+
include Train::Platforms::Detect::Helpers::Linux
|
10
|
+
include Train::Platforms::Detect::Helpers::Windows
|
11
|
+
|
12
|
+
def ruby_host_os(regex)
|
13
|
+
::RbConfig::CONFIG['host_os'] =~ regex
|
14
|
+
end
|
15
|
+
|
16
|
+
def winrm?
|
17
|
+
Object.const_defined?('Train::Transports::WinRM::Connection') &&
|
18
|
+
@backend.class == Train::Transports::WinRM::Connection
|
19
|
+
end
|
20
|
+
|
21
|
+
def unix_file_contents(path)
|
22
|
+
# keep a log of files incase multiple checks call the same one
|
23
|
+
return @files[path] if @files.key?(path)
|
24
|
+
|
25
|
+
res = @backend.run_command("test -f #{path} && cat #{path}")
|
26
|
+
# ignore files that can't be read
|
27
|
+
@files[path] = res.exit_status.zero? ? res.stdout : nil
|
28
|
+
@files[path]
|
29
|
+
end
|
30
|
+
|
31
|
+
def unix_file_exist?(path)
|
32
|
+
@backend.run_command("test -f #{path}").exit_status.zero?
|
33
|
+
end
|
34
|
+
|
35
|
+
def command_output(cmd)
|
36
|
+
res = @backend.run_command(cmd).stdout
|
37
|
+
res.strip! unless res.nil?
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
def unix_uname_s
|
42
|
+
return @uname[:s] if @uname.key?(:s)
|
43
|
+
@uname[:s] = command_output('uname -s')
|
44
|
+
end
|
45
|
+
|
46
|
+
def unix_uname_r
|
47
|
+
return @uname[:r] if @uname.key?(:r)
|
48
|
+
@uname[:r] = command_output('uname -r')
|
49
|
+
end
|
50
|
+
|
51
|
+
def unix_uname_m
|
52
|
+
return @uname[:m] if @uname.key?(:m)
|
53
|
+
@uname[:m] = command_output('uname -m')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Train::Platforms::Detect::Helpers
|
4
|
+
module Linux
|
5
|
+
def redhatish_platform(conf)
|
6
|
+
conf =~ /^red hat/i ? 'redhat' : /(\w+)/i.match(conf)[1].downcase
|
7
|
+
end
|
8
|
+
|
9
|
+
def redhatish_version(conf)
|
10
|
+
case conf
|
11
|
+
when /rawhide/i
|
12
|
+
/((\d+) \(Rawhide\))/i.match(conf)[1].downcase
|
13
|
+
when /derived from .*linux/i
|
14
|
+
/Linux ((\d+|\.)+)/i.match(conf)[1]
|
15
|
+
else
|
16
|
+
/release ([\d\.]+)/.match(conf)[1]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def linux_os_release
|
21
|
+
data = unix_file_contents('/etc/os-release')
|
22
|
+
return if data.nil?
|
23
|
+
|
24
|
+
os_info = parse_os_release_info(data)
|
25
|
+
cisco_info_file = os_info['CISCO_RELEASE_INFO']
|
26
|
+
if cisco_info_file
|
27
|
+
os_info.merge!(parse_os_release_info(unix_file_contents(cisco_info_file)))
|
28
|
+
end
|
29
|
+
|
30
|
+
os_info
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_os_release_info(raw)
|
34
|
+
return {} if raw.nil?
|
35
|
+
|
36
|
+
raw.lines.each_with_object({}) do |line, memo|
|
37
|
+
line.strip!
|
38
|
+
next if line.empty?
|
39
|
+
key, value = line.split('=', 2)
|
40
|
+
memo[key] = value.gsub(/\A"|"\Z/, '') unless value.empty?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def lsb_config(content)
|
45
|
+
id = /^DISTRIB_ID=["']?(.+?)["']?$/.match(content)
|
46
|
+
release = /^DISTRIB_RELEASE=["']?(.+?)["']?$/.match(content)
|
47
|
+
codename = /^DISTRIB_CODENAME=["']?(.+?)["']?$/.match(content)
|
48
|
+
{
|
49
|
+
id: id.nil? ? nil : id[1],
|
50
|
+
release: release.nil? ? nil : release[1],
|
51
|
+
codename: codename.nil? ? nil : codename[1],
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def lsb_release(content)
|
56
|
+
id = /^Distributor ID:\s+(.+)$/.match(content)
|
57
|
+
release = /^Release:\s+(.+)$/.match(content)
|
58
|
+
codename = /^Codename:\s+(.+)$/.match(content)
|
59
|
+
{
|
60
|
+
id: id.nil? ? nil : id[1],
|
61
|
+
release: release.nil? ? nil : release[1],
|
62
|
+
codename: codename.nil? ? nil : codename[1],
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def read_linux_lsb
|
67
|
+
return @lsb unless @lsb.empty?
|
68
|
+
if !(raw = unix_file_contents('/etc/lsb-release')).nil?
|
69
|
+
@lsb = lsb_config(raw)
|
70
|
+
elsif !(raw = unix_file_contents('/usr/bin/lsb-release')).nil?
|
71
|
+
@lsb = lsb_release(raw)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,14 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# This is heavily based on:
|
6
|
-
#
|
7
|
-
# OHAI https://github.com/chef/ohai
|
8
|
-
# by Adam Jacob, Chef Software Inc
|
9
|
-
#
|
10
|
-
module Train::Extras
|
11
|
-
module DetectWindows
|
2
|
+
|
3
|
+
module Train::Platforms::Detect::Helpers
|
4
|
+
module Windows
|
12
5
|
def detect_windows
|
13
6
|
res = @backend.run_command('cmd /c ver')
|
14
7
|
return false if res.exit_status != 0 or res.stdout.empty?
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'train/platforms/detect/helpers/os_common'
|
4
|
+
|
5
|
+
module Train::Platforms::Detect
|
6
|
+
class Scanner
|
7
|
+
include Train::Platforms::Detect::Helpers::OSCommon
|
8
|
+
|
9
|
+
def initialize(backend)
|
10
|
+
@backend = backend
|
11
|
+
@platform = {}
|
12
|
+
@family_hierarchy = []
|
13
|
+
|
14
|
+
# detect cache variables
|
15
|
+
@files = {}
|
16
|
+
@uname = {}
|
17
|
+
@lsb = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Main detect method to scan all platforms for a match
|
21
|
+
#
|
22
|
+
# @return Train::Platform instance or error if none found
|
23
|
+
def scan
|
24
|
+
# start with the platform/families who have no families (the top levels)
|
25
|
+
top = Train::Platforms.top_platforms
|
26
|
+
top.each do |_name, plat|
|
27
|
+
# we are doing a instance_eval here to make sure we have the proper
|
28
|
+
# context with all the detect helper methods
|
29
|
+
next unless instance_eval(&plat.detect) == true
|
30
|
+
|
31
|
+
# if we have a match start looking at the children
|
32
|
+
plat_result = scan_children(plat)
|
33
|
+
next if plat_result.nil?
|
34
|
+
|
35
|
+
# return platform to backend
|
36
|
+
@family_hierarchy << plat.name
|
37
|
+
return get_platform(plat_result)
|
38
|
+
end
|
39
|
+
|
40
|
+
fail Train::PlatformDetectionFailed, 'Sorry, we are unable to detect your platform'
|
41
|
+
end
|
42
|
+
|
43
|
+
def scan_children(parent)
|
44
|
+
parent.children.each do |plat, condition|
|
45
|
+
next unless instance_eval(&plat.detect) == true
|
46
|
+
|
47
|
+
if plat.class == Train::Platforms::Platform
|
48
|
+
@platform[:family] = parent.name
|
49
|
+
return plat if condition.empty? || check_condition(condition)
|
50
|
+
elsif plat.class == Train::Platforms::Family
|
51
|
+
plat = scan_family_children(plat)
|
52
|
+
return plat unless plat.nil?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def scan_family_children(plat)
|
60
|
+
child_result = scan_children(plat) unless plat.children.nil?
|
61
|
+
return if child_result.nil?
|
62
|
+
@family_hierarchy << plat.name
|
63
|
+
child_result
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_condition(condition)
|
67
|
+
condition.each do |k, v|
|
68
|
+
op, expected = v.strip.split(' ')
|
69
|
+
op = '==' if op == '='
|
70
|
+
return false if @platform[k].nil? || !instance_eval("'#{@platform[k]}' #{op} '#{expected}'")
|
71
|
+
end
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_platform(plat)
|
77
|
+
plat.backend = @backend
|
78
|
+
plat.platform = @platform
|
79
|
+
plat.add_platform_methods
|
80
|
+
plat.family_hierarchy = @family_hierarchy
|
81
|
+
plat
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|