train-core 3.8.7 → 3.10.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/lib/train/errors.rb +3 -0
- data/lib/train/platforms/detect/helpers/os_common.rb +6 -1
- data/lib/train/platforms/detect/helpers/os_windows.rb +1 -1
- data/lib/train/platforms/detect/uuid.rb +3 -2
- data/lib/train/transports/podman.rb +157 -0
- data/lib/train/transports/ssh_connection.rb +10 -1
- data/lib/train/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 579bb940034fbb7c1d8f6e8025b0d364e5b78f2161efd6155a0f7d65f03af7e0
|
4
|
+
data.tar.gz: f5ffb30dfd921debde3e54dc2f88d0f9c41644b02ec7bf3eb6d32797dcc81bc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6972393f3e6721198c850213d00e120c49668fe29fe60d50d2d465bf5839d9e0ee7281d14e98143d2bd9bb33130f6bee9e859e9c111c490dfdca02ea0d96a27
|
7
|
+
data.tar.gz: a68a449c540c36712f68b69ef6103955e4bb10287c98b4448a65b0b103bdb8e9cbf401a3316bdca6a347e9fa85dd55fa4c1619fcb7ff4cc379fecb33032918b0
|
data/lib/train/errors.rb
CHANGED
@@ -38,6 +38,9 @@ module Train
|
|
38
38
|
# Exception for when no platform can be detected.
|
39
39
|
class PlatformDetectionFailed < Error; end
|
40
40
|
|
41
|
+
# Exception for when no uuid for the platform can be detected.
|
42
|
+
class PlatformUuidDetectionFailed < Error; end
|
43
|
+
|
41
44
|
# Exception for when a invalid cache type is passed.
|
42
45
|
class UnknownCacheType < Error; end
|
43
46
|
|
@@ -97,6 +97,12 @@ module Train::Platforms::Detect::Helpers
|
|
97
97
|
return @cache[:cisco] = { version: m[2], model: m[1], type: "ios-xe" }
|
98
98
|
end
|
99
99
|
|
100
|
+
# CSR 1000V (for example) does not specify model
|
101
|
+
m = res.match(/Cisco IOS XE Software, Version (\d+\.\d+\.\d+[A-Z]*)/)
|
102
|
+
unless m.nil?
|
103
|
+
return @cache[:cisco] = { version: m[1], type: "ios-xe" }
|
104
|
+
end
|
105
|
+
|
100
106
|
m = res.match(/Cisco Nexus Operating System \(NX-OS\) Software/)
|
101
107
|
unless m.nil?
|
102
108
|
v = res[/^\s*system:\s+version (\d+\.\d+)/, 1]
|
@@ -122,7 +128,6 @@ module Train::Platforms::Detect::Helpers
|
|
122
128
|
end
|
123
129
|
|
124
130
|
def unix_uuid_from_machine_file
|
125
|
-
# require 'pry';binding.pry
|
126
131
|
%W{
|
127
132
|
/etc/chef/chef_guid
|
128
133
|
#{ENV["HOME"]}/.chef/chef_guid
|
@@ -51,7 +51,7 @@ module Train::Platforms::Detect::Helpers
|
|
51
51
|
|
52
52
|
def local_windows?
|
53
53
|
@backend.class.to_s == "Train::Transports::Local::Connection" &&
|
54
|
-
ruby_host_os(/mswin|
|
54
|
+
ruby_host_os(/mswin|mingw|windows/)
|
55
55
|
end
|
56
56
|
|
57
57
|
# reads os name and version from wmic
|
@@ -20,12 +20,13 @@ module Train::Platforms::Detect
|
|
20
20
|
elsif @platform.windows?
|
21
21
|
windows_uuid
|
22
22
|
else
|
23
|
-
|
23
|
+
# Checking "unknown" :uuid_command which is set for mock transport.
|
24
|
+
if @platform[:uuid_command] && !@platform[:uuid_command] == "unknown"
|
24
25
|
result = @backend.run_command(@platform[:uuid_command])
|
25
26
|
return uuid_from_string(result.stdout.chomp) if result.exit_status == 0 && !result.stdout.empty?
|
26
27
|
end
|
27
28
|
|
28
|
-
raise "Could not find platform uuid! Please set a uuid_command for your platform."
|
29
|
+
raise Train::PlatformUuidDetectionFailed.new("Could not find platform uuid! Please set a uuid_command for your platform.")
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "docker"
|
2
|
+
require_relative "../errors"
|
3
|
+
|
4
|
+
module Train::Transports
|
5
|
+
class Podman < Train.plugin(1)
|
6
|
+
|
7
|
+
name "podman"
|
8
|
+
|
9
|
+
include_options Train::Extras::CommandWrapper
|
10
|
+
option :host, required: true
|
11
|
+
option :podman_url, required: false
|
12
|
+
|
13
|
+
def connection(state = {}, &block)
|
14
|
+
opts = merge_options(options, state || {})
|
15
|
+
|
16
|
+
validate_options(opts)
|
17
|
+
|
18
|
+
if @connection && @connection_options == opts
|
19
|
+
reuse_connection(&block)
|
20
|
+
else
|
21
|
+
create_new_connection(opts, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Creates a new Podman connection instance and save it for potential future
|
28
|
+
# reuse.
|
29
|
+
#
|
30
|
+
# @param options [Hash] connection options
|
31
|
+
# @return [Podman::Connection] a Podman connection instance
|
32
|
+
# @api private
|
33
|
+
def create_new_connection(options, &block)
|
34
|
+
if @connection
|
35
|
+
logger.debug("[Podman] shutting previous connection #{@connection}")
|
36
|
+
@connection.close
|
37
|
+
end
|
38
|
+
|
39
|
+
@connection_options = options
|
40
|
+
@connection = Connection.new(options, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return the last saved Podman connection instance.
|
44
|
+
#
|
45
|
+
# @return [Podman::Connection] a Podman connection instance
|
46
|
+
# @api private
|
47
|
+
def reuse_connection
|
48
|
+
logger.debug("[Podman] reusing existing connection #{@connection}")
|
49
|
+
yield @connection if block_given?
|
50
|
+
@connection
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Train::Transports::Podman
|
55
|
+
class Connection < BaseConnection
|
56
|
+
def initialize(options)
|
57
|
+
super(options)
|
58
|
+
|
59
|
+
@id = options[:host]
|
60
|
+
|
61
|
+
if RUBY_PLATFORM =~ /windows|mswin|msys|mingw|cygwin/
|
62
|
+
raise "Unsupported host platform."
|
63
|
+
end
|
64
|
+
|
65
|
+
# Currently Podman url can be set using option and setting the environment variable.
|
66
|
+
uid = Process.uid
|
67
|
+
podman_url = options[:podman_url] || ENV["CONTAINER_HOST"]
|
68
|
+
podman_url ||= "unix:///run/podman/podman.sock" if uid == 0
|
69
|
+
podman_url ||= "unix:///run/user/#{uid}/podman/podman.sock"
|
70
|
+
|
71
|
+
Docker.url = podman_url
|
72
|
+
|
73
|
+
# Using docker-api ruby library to fetch the Podman container data.
|
74
|
+
@container = ::Docker::Container.get(@id) ||
|
75
|
+
raise("Can't find Podman container #{@id}")
|
76
|
+
@cmd_wrapper = nil
|
77
|
+
@cmd_wrapper = CommandWrapper.load(self, @options)
|
78
|
+
@probably_windows = nil
|
79
|
+
rescue Excon::Error::Socket
|
80
|
+
raise Train::TransportError, "Unable to connect to Podman using #{podman_url}"
|
81
|
+
rescue Docker::Error::NotFoundError => e
|
82
|
+
raise Train::TransportError, "Container Not Found: #{e.message}"
|
83
|
+
rescue Docker::Error::ServerError => e
|
84
|
+
raise Train::TransportError, "#{e.message}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def close
|
88
|
+
# nothing to do at the moment
|
89
|
+
end
|
90
|
+
|
91
|
+
def uri
|
92
|
+
if @container.nil?
|
93
|
+
"podman://#{@id}"
|
94
|
+
else
|
95
|
+
"podman://#{@container.id}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def unique_identifier
|
100
|
+
@container.nil? ? @id : @container.id # default uuid set to the podman host.
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def file_via_connection(path)
|
106
|
+
if os.aix?
|
107
|
+
Train::File::Remote::Aix.new(self, path)
|
108
|
+
elsif os.solaris?
|
109
|
+
Train::File::Remote::Unix.new(self, path)
|
110
|
+
elsif os.windows?
|
111
|
+
Train::File::Remote::Windows.new(self, path)
|
112
|
+
else
|
113
|
+
Train::File::Remote::Linux.new(self, path)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def run_command_via_connection(cmd, &_data_handler)
|
118
|
+
cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
|
119
|
+
|
120
|
+
# Cannot use os.windows? here because it calls run_command_via_connection,
|
121
|
+
# causing infinite recursion during initial platform detection
|
122
|
+
if sniff_for_windows?
|
123
|
+
invocation = cmd_run_command(cmd)
|
124
|
+
else
|
125
|
+
invocation = sh_run_command(cmd)
|
126
|
+
end
|
127
|
+
stdout, stderr, exit_status = @container.exec(
|
128
|
+
invocation, user: @options[:user]
|
129
|
+
)
|
130
|
+
CommandResult.new(stdout.join, stderr.join, exit_status)
|
131
|
+
rescue ::Docker::Error::DockerError => _
|
132
|
+
raise
|
133
|
+
rescue => _
|
134
|
+
# @TODO: differentiate any other error
|
135
|
+
raise
|
136
|
+
end
|
137
|
+
|
138
|
+
def sh_run_command(cmd)
|
139
|
+
["/bin/sh", "-c", cmd]
|
140
|
+
end
|
141
|
+
|
142
|
+
def cmd_run_command(cmd)
|
143
|
+
["cmd.exe", "/s", "/c", cmd]
|
144
|
+
end
|
145
|
+
|
146
|
+
def sniff_for_windows?
|
147
|
+
return @probably_windows unless @probably_windows.nil?
|
148
|
+
|
149
|
+
# Run a command using /bin/sh, which should fail under Windows
|
150
|
+
stdout, _stderr, _exit_status = @container.exec(
|
151
|
+
sh_run_command("true"), user: @options[:user]
|
152
|
+
)
|
153
|
+
@probably_windows = !!stdout.detect { |l| l.include? "failure in a Windows system call" }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -326,7 +326,16 @@ class Train::Transports::SSH
|
|
326
326
|
cmd = @cmd_wrapper.run(cmd) if @cmd_wrapper
|
327
327
|
|
328
328
|
# Timeout the command if requested and able
|
329
|
-
|
329
|
+
if timeout && timeoutable?(cmd)
|
330
|
+
# if cmd start with sudo then we need to make sure the timeout should be prepend with sudo else actual timeout is not working.
|
331
|
+
if cmd.strip.split[0] == "sudo"
|
332
|
+
split_cmd = cmd.strip.split
|
333
|
+
split_cmd[0] = "sudo timeout #{timeout}s"
|
334
|
+
cmd = split_cmd.join(" ")
|
335
|
+
else
|
336
|
+
cmd = "timeout #{timeout}s #{cmd}"
|
337
|
+
end
|
338
|
+
end
|
330
339
|
|
331
340
|
logger.debug("[SSH] #{self} cmd = #{cmd}")
|
332
341
|
|
data/lib/train/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: train-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef InSpec Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -162,6 +162,7 @@ files:
|
|
162
162
|
- lib/train/transports/cisco_ios_connection.rb
|
163
163
|
- lib/train/transports/local.rb
|
164
164
|
- lib/train/transports/mock.rb
|
165
|
+
- lib/train/transports/podman.rb
|
165
166
|
- lib/train/transports/ssh.rb
|
166
167
|
- lib/train/transports/ssh_connection.rb
|
167
168
|
- lib/train/version.rb
|
@@ -181,7 +182,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
181
182
|
requirements:
|
182
183
|
- - ">="
|
183
184
|
- !ruby/object:Gem::Version
|
184
|
-
version: '2.
|
185
|
+
version: '2.7'
|
185
186
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
187
|
requirements:
|
187
188
|
- - ">="
|