train 2.1.7 → 2.1.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/train.rb +20 -20
- data/lib/train/errors.rb +1 -1
- data/lib/train/extras.rb +2 -2
- data/lib/train/extras/command_wrapper.rb +24 -24
- data/lib/train/extras/stat.rb +27 -27
- data/lib/train/file.rb +30 -30
- data/lib/train/file/local.rb +8 -8
- data/lib/train/file/local/unix.rb +5 -5
- data/lib/train/file/local/windows.rb +1 -1
- data/lib/train/file/remote.rb +8 -8
- data/lib/train/file/remote/aix.rb +1 -1
- data/lib/train/file/remote/linux.rb +2 -2
- data/lib/train/file/remote/qnx.rb +8 -8
- data/lib/train/file/remote/unix.rb +10 -14
- data/lib/train/file/remote/windows.rb +5 -5
- data/lib/train/globals.rb +1 -1
- data/lib/train/options.rb +8 -8
- data/lib/train/platforms.rb +8 -8
- data/lib/train/platforms/common.rb +1 -1
- data/lib/train/platforms/detect/helpers/os_common.rb +36 -32
- data/lib/train/platforms/detect/helpers/os_linux.rb +12 -12
- data/lib/train/platforms/detect/helpers/os_windows.rb +27 -29
- data/lib/train/platforms/detect/scanner.rb +4 -4
- data/lib/train/platforms/detect/specifications/api.rb +8 -8
- data/lib/train/platforms/detect/specifications/os.rb +252 -252
- data/lib/train/platforms/detect/uuid.rb +5 -7
- data/lib/train/platforms/platform.rb +9 -5
- data/lib/train/plugin_test_helper.rb +12 -12
- data/lib/train/plugins.rb +5 -5
- data/lib/train/plugins/base_connection.rb +13 -13
- data/lib/train/plugins/transport.rb +7 -7
- data/lib/train/transports/azure.rb +23 -23
- data/lib/train/transports/cisco_ios_connection.rb +20 -20
- data/lib/train/transports/clients/azure/graph_rbac.rb +2 -2
- data/lib/train/transports/clients/azure/vault.rb +4 -4
- data/lib/train/transports/docker.rb +4 -10
- data/lib/train/transports/gcp.rb +23 -23
- data/lib/train/transports/helpers/azure/file_credentials.rb +8 -8
- data/lib/train/transports/helpers/azure/file_parser.rb +1 -1
- data/lib/train/transports/helpers/azure/subscription_number_file_parser.rb +1 -1
- data/lib/train/transports/local.rb +22 -22
- data/lib/train/transports/mock.rb +33 -35
- data/lib/train/transports/ssh.rb +47 -47
- data/lib/train/transports/ssh_connection.rb +28 -28
- data/lib/train/transports/vmware.rb +32 -34
- data/lib/train/transports/winrm.rb +37 -37
- data/lib/train/transports/winrm_connection.rb +12 -12
- data/lib/train/version.rb +1 -1
- metadata +2 -2
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require
|
3
|
+
require "azure_graph_rbac"
|
4
4
|
|
5
5
|
# Wrapper class for ::Azure::GraphRbac::Profiles::Latest::Client allowing custom configuration,
|
6
6
|
# for example, defining additional settings for the ::MsRestAzure::ApplicationTokenProvider.
|
@@ -20,7 +20,7 @@ class GraphRbac
|
|
20
20
|
credentials[:tenant_id],
|
21
21
|
credentials[:client_id],
|
22
22
|
credentials[:client_secret],
|
23
|
-
settings
|
23
|
+
settings
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require
|
3
|
+
require "azure_mgmt_key_vault"
|
4
4
|
|
5
5
|
# Wrapper class for ::Azure::KeyVault::Profiles::Latest::Mgmt::Client allowing custom configuration,
|
6
6
|
# for example, defining additional settings for the ::MsRestAzure::ApplicationTokenProvider.
|
7
7
|
class Vault
|
8
8
|
AUTH_ENDPOINT = MsRestAzure::AzureEnvironments::AzureCloud.active_directory_endpoint_url
|
9
|
-
RESOURCE_ENDPOINT =
|
9
|
+
RESOURCE_ENDPOINT = "https://vault.azure.net".freeze
|
10
10
|
|
11
11
|
def self.client(vault_name, credentials)
|
12
|
-
raise ::Train::UserError,
|
12
|
+
raise ::Train::UserError, "Vault Name cannot be nil" if vault_name.nil?
|
13
13
|
|
14
14
|
credentials[:credentials] = ::MsRest::TokenCredentials.new(provider(credentials))
|
15
15
|
credentials[:base_url] = api_endpoint(vault_name)
|
@@ -22,7 +22,7 @@ class Vault
|
|
22
22
|
credentials[:tenant_id],
|
23
23
|
credentials[:client_id],
|
24
24
|
credentials[:client_secret],
|
25
|
-
settings
|
25
|
+
settings
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
@@ -1,13 +1,8 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Author:: Dominik Richter
|
4
|
-
# Author:: Christoph Hartmann
|
5
|
-
|
6
|
-
require 'docker'
|
1
|
+
require "docker"
|
7
2
|
|
8
3
|
module Train::Transports
|
9
4
|
class Docker < Train.plugin(1)
|
10
|
-
name
|
5
|
+
name "docker"
|
11
6
|
|
12
7
|
include_options Train::Extras::CommandWrapper
|
13
8
|
option :host, required: true
|
@@ -59,10 +54,9 @@ class Train::Transports::Docker
|
|
59
54
|
super(conf)
|
60
55
|
@id = options[:host]
|
61
56
|
@container = ::Docker::Container.get(@id) ||
|
62
|
-
|
57
|
+
raise("Can't find Docker container #{@id}")
|
63
58
|
@cmd_wrapper = nil
|
64
59
|
@cmd_wrapper = CommandWrapper.load(self, @options)
|
65
|
-
self
|
66
60
|
end
|
67
61
|
|
68
62
|
def close
|
@@ -93,7 +87,7 @@ class Train::Transports::Docker
|
|
93
87
|
cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
|
94
88
|
stdout, stderr, exit_status = @container.exec(
|
95
89
|
[
|
96
|
-
|
90
|
+
"/bin/sh", "-c", cmd
|
97
91
|
])
|
98
92
|
CommandResult.new(stdout.join, stderr.join, exit_status)
|
99
93
|
rescue ::Docker::Error::DockerError => _
|
data/lib/train/transports/gcp.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
3
|
+
require "train/plugins"
|
4
|
+
require "google/apis"
|
5
|
+
require "google/apis/cloudresourcemanager_v1"
|
6
|
+
require "google/apis/compute_v1"
|
7
|
+
require "google/apis/storage_v1"
|
8
|
+
require "google/apis/iam_v1"
|
9
|
+
require "google/apis/admin_directory_v1"
|
10
|
+
require "googleauth"
|
11
11
|
|
12
12
|
module Train::Transports
|
13
13
|
class Gcp < Train.plugin(1)
|
14
|
-
name
|
14
|
+
name "gcp"
|
15
15
|
|
16
16
|
# GCP will look automatically for the below env var for service accounts etc. :
|
17
17
|
option :google_application_credentials, required: false do
|
18
|
-
ENV[
|
18
|
+
ENV["GOOGLE_APPLICATION_CREDENTIALS"]
|
19
19
|
end
|
20
20
|
# see https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application
|
21
21
|
# In the absence of this, the client is expected to have already set up local credentials via:
|
@@ -25,10 +25,10 @@ module Train::Transports
|
|
25
25
|
# https://cloud.google.com/compute/docs/regions-zones/changing-default-zone-region
|
26
26
|
# can also specify project via env var:
|
27
27
|
option :google_cloud_project, required: false do
|
28
|
-
ENV[
|
28
|
+
ENV["GOOGLE_CLOUD_PROJECT"]
|
29
29
|
end
|
30
30
|
option :google_super_admin_email, required: false do
|
31
|
-
ENV[
|
31
|
+
ENV["GOOGLE_SUPER_ADMIN_EMAIL"]
|
32
32
|
end
|
33
33
|
|
34
34
|
def connection(_ = nil)
|
@@ -40,7 +40,7 @@ module Train::Transports
|
|
40
40
|
super(options)
|
41
41
|
|
42
42
|
# additional GCP platform metadata
|
43
|
-
release = Gem.loaded_specs[
|
43
|
+
release = Gem.loaded_specs["google-api-client"].version
|
44
44
|
@platform_details = { release: "google-api-client-v#{release}" }
|
45
45
|
|
46
46
|
# Initialize the client object cache
|
@@ -51,7 +51,7 @@ module Train::Transports
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def platform
|
54
|
-
force_platform!(
|
54
|
+
force_platform!("gcp", @platform_details)
|
55
55
|
end
|
56
56
|
|
57
57
|
# Instantiate some named classes for ease of use
|
@@ -72,7 +72,7 @@ module Train::Transports
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def gcp_admin_client
|
75
|
-
scopes = [
|
75
|
+
scopes = ["https://www.googleapis.com/auth/admin.directory.user.readonly"]
|
76
76
|
authorization = Google::Auth.get_application_default(scopes).dup
|
77
77
|
# Use of the Admin API requires delegation (impersonation). An email address of a Super Admin in
|
78
78
|
# the G Suite account may be required.
|
@@ -88,13 +88,13 @@ module Train::Transports
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def connect
|
91
|
-
ENV[
|
92
|
-
ENV[
|
91
|
+
ENV["GOOGLE_APPLICATION_CREDENTIALS"] = @options[:google_application_credentials] if @options[:google_application_credentials]
|
92
|
+
ENV["GOOGLE_CLOUD_PROJECT"] = @options[:google_cloud_project] if @options[:google_cloud_project]
|
93
93
|
# GCP initialization
|
94
|
-
scopes = [
|
95
|
-
|
94
|
+
scopes = ["https://www.googleapis.com/auth/cloud-platform",
|
95
|
+
"https://www.googleapis.com/auth/compute"]
|
96
96
|
authorization = Google::Auth.get_application_default(scopes)
|
97
|
-
Google::Apis::ClientOptions.default.application_name =
|
97
|
+
Google::Apis::ClientOptions.default.application_name = "chef-inspec-train"
|
98
98
|
Google::Apis::ClientOptions.default.application_version = Train::VERSION
|
99
99
|
Google::Apis::RequestOptions.default.authorization = authorization
|
100
100
|
end
|
@@ -104,11 +104,11 @@ module Train::Transports
|
|
104
104
|
end
|
105
105
|
|
106
106
|
def unique_identifier
|
107
|
-
unique_id =
|
107
|
+
unique_id = "default"
|
108
108
|
# use auth client_id for users (issuer is nil)
|
109
|
-
unique_id=gcp_iam_client.request_options.authorization.client_id unless gcp_iam_client.request_options.authorization.client_id.nil?
|
109
|
+
unique_id = gcp_iam_client.request_options.authorization.client_id unless gcp_iam_client.request_options.authorization.client_id.nil?
|
110
110
|
# for service account credentials (client_id is nil)
|
111
|
-
unique_id=gcp_iam_client.request_options.authorization.issuer unless gcp_iam_client.request_options.authorization.issuer.nil?
|
111
|
+
unique_id = gcp_iam_client.request_options.authorization.issuer unless gcp_iam_client.request_options.authorization.issuer.nil?
|
112
112
|
unique_id
|
113
113
|
end
|
114
114
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "inifile"
|
4
|
+
require "train/transports/helpers/azure/file_parser"
|
5
|
+
require "train/transports/helpers/azure/subscription_number_file_parser"
|
6
|
+
require "train/transports/helpers/azure/subscription_id_file_parser"
|
7
7
|
|
8
8
|
module Train::Transports
|
9
9
|
module Helpers
|
@@ -13,7 +13,7 @@ module Train::Transports
|
|
13
13
|
return {} if credentials_file.nil?
|
14
14
|
return {} unless ::File.readable?(credentials_file)
|
15
15
|
credentials = IniFile.load(::File.expand_path(credentials_file))
|
16
|
-
subscription_id = parser(subscription_id, ENV[
|
16
|
+
subscription_id = parser(subscription_id, ENV["AZURE_SUBSCRIPTION_NUMBER"], credentials).subscription_id
|
17
17
|
creds(subscription_id, credentials)
|
18
18
|
end
|
19
19
|
|
@@ -30,9 +30,9 @@ module Train::Transports
|
|
30
30
|
def self.creds(subscription_id, credentials)
|
31
31
|
{
|
32
32
|
subscription_id: subscription_id,
|
33
|
-
tenant_id:
|
34
|
-
client_id:
|
35
|
-
client_secret:
|
33
|
+
tenant_id: credentials[subscription_id]["tenant_id"],
|
34
|
+
client_id: credentials[subscription_id]["client_id"],
|
35
|
+
client_secret: credentials[subscription_id]["client_secret"],
|
36
36
|
}
|
37
37
|
end
|
38
38
|
end
|
@@ -13,7 +13,7 @@ module Train::Transports
|
|
13
13
|
def validate!
|
14
14
|
return if @credentials.sections.count == 1
|
15
15
|
|
16
|
-
raise
|
16
|
+
raise "Credentials file must have one entry. Check your credentials file. If you have more than one entry set AZURE_SUBSCRIPTION_ID environment variable."
|
17
17
|
end
|
18
18
|
|
19
19
|
def subscription_id
|
@@ -3,13 +3,13 @@
|
|
3
3
|
# author: Dominik Richter
|
4
4
|
# author: Christoph Hartmann
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
6
|
+
require "train/plugins"
|
7
|
+
require "train/errors"
|
8
|
+
require "mixlib/shellout"
|
9
9
|
|
10
10
|
module Train::Transports
|
11
11
|
class Local < Train.plugin(1)
|
12
|
-
name
|
12
|
+
name "local"
|
13
13
|
|
14
14
|
class PipeError < Train::TransportError; end
|
15
15
|
|
@@ -33,7 +33,7 @@ module Train::Transports
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def uri
|
36
|
-
|
36
|
+
"local://"
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
@@ -41,10 +41,10 @@ module Train::Transports
|
|
41
41
|
def select_runner(options)
|
42
42
|
if os.windows?
|
43
43
|
# Force a 64 bit poweshell if needed
|
44
|
-
if RUBY_PLATFORM ==
|
44
|
+
if RUBY_PLATFORM == "i386-mingw32" && os.arch == "x86_64"
|
45
45
|
powershell_cmd = "#{ENV['SystemRoot']}\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe"
|
46
46
|
else
|
47
|
-
powershell_cmd =
|
47
|
+
powershell_cmd = "powershell"
|
48
48
|
end
|
49
49
|
|
50
50
|
# Attempt to use a named pipe but fallback to ShellOut if that fails
|
@@ -67,7 +67,7 @@ module Train::Transports
|
|
67
67
|
when :windows_shell
|
68
68
|
WindowsShellRunner.new
|
69
69
|
else
|
70
|
-
|
70
|
+
raise "Runner type `#{command_runner}` not supported"
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -82,7 +82,7 @@ module Train::Transports
|
|
82
82
|
res.run_command
|
83
83
|
Local::CommandResult.new(res.stdout, res.stderr, res.exitstatus)
|
84
84
|
rescue Errno::ENOENT => _
|
85
|
-
CommandResult.new(
|
85
|
+
CommandResult.new("", "", 1)
|
86
86
|
end
|
87
87
|
|
88
88
|
def file_via_connection(path)
|
@@ -112,10 +112,10 @@ module Train::Transports
|
|
112
112
|
end
|
113
113
|
|
114
114
|
class WindowsShellRunner
|
115
|
-
require
|
116
|
-
require
|
115
|
+
require "json"
|
116
|
+
require "base64"
|
117
117
|
|
118
|
-
def initialize(powershell_cmd =
|
118
|
+
def initialize(powershell_cmd = "powershell")
|
119
119
|
@powershell_cmd = powershell_cmd
|
120
120
|
end
|
121
121
|
|
@@ -124,7 +124,7 @@ module Train::Transports
|
|
124
124
|
script = "$ProgressPreference='SilentlyContinue';" + script
|
125
125
|
|
126
126
|
# Encode script so PowerShell can use it
|
127
|
-
script = script.encode(
|
127
|
+
script = script.encode("UTF-16LE", "UTF-8")
|
128
128
|
base64_script = Base64.strict_encode64(script)
|
129
129
|
|
130
130
|
cmd = "#{@powershell_cmd} -NoProfile -EncodedCommand #{base64_script}"
|
@@ -136,14 +136,14 @@ module Train::Transports
|
|
136
136
|
end
|
137
137
|
|
138
138
|
class WindowsPipeRunner
|
139
|
-
require
|
140
|
-
require
|
141
|
-
require
|
139
|
+
require "json"
|
140
|
+
require "base64"
|
141
|
+
require "securerandom"
|
142
142
|
|
143
|
-
def initialize(powershell_cmd =
|
143
|
+
def initialize(powershell_cmd = "powershell")
|
144
144
|
@powershell_cmd = powershell_cmd
|
145
145
|
@pipe = acquire_pipe
|
146
|
-
|
146
|
+
raise PipeError if @pipe.nil?
|
147
147
|
end
|
148
148
|
|
149
149
|
def run_command(cmd)
|
@@ -167,7 +167,7 @@ module Train::Transports
|
|
167
167
|
# PowerShell needs time to create pipe.
|
168
168
|
100.times do
|
169
169
|
begin
|
170
|
-
pipe = open("//./pipe/#{pipe_name}",
|
170
|
+
pipe = open("//./pipe/#{pipe_name}", "r+")
|
171
171
|
break
|
172
172
|
rescue
|
173
173
|
sleep 0.1
|
@@ -178,7 +178,7 @@ module Train::Transports
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def start_pipe_server(pipe_name)
|
181
|
-
require
|
181
|
+
require "win32/process"
|
182
182
|
|
183
183
|
script = <<-EOF
|
184
184
|
$ErrorActionPreference = 'Stop'
|
@@ -213,14 +213,14 @@ module Train::Transports
|
|
213
213
|
}
|
214
214
|
EOF
|
215
215
|
|
216
|
-
utf8_script = script.encode(
|
216
|
+
utf8_script = script.encode("UTF-16LE", "UTF-8")
|
217
217
|
base64_script = Base64.strict_encode64(utf8_script)
|
218
218
|
cmd = "#{@powershell_cmd} -NoProfile -ExecutionPolicy bypass -NonInteractive -EncodedCommand #{base64_script}"
|
219
219
|
|
220
220
|
server_pid = Process.create(command_line: cmd).process_id
|
221
221
|
|
222
222
|
# Ensure process is killed when the Train process exits
|
223
|
-
at_exit { Process.kill(
|
223
|
+
at_exit { Process.kill("KILL", server_pid) }
|
224
224
|
end
|
225
225
|
end
|
226
226
|
end
|
@@ -1,11 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'train/plugins'
|
4
|
-
require 'digest'
|
1
|
+
require "train/plugins"
|
2
|
+
require "digest"
|
5
3
|
|
6
4
|
module Train::Transports
|
7
5
|
class Mock < Train.plugin(1)
|
8
|
-
name
|
6
|
+
name "mock"
|
9
7
|
|
10
8
|
def initialize(conf = nil)
|
11
9
|
@conf = conf || {}
|
@@ -17,39 +15,39 @@ module Train::Transports
|
|
17
15
|
end
|
18
16
|
|
19
17
|
def to_s
|
20
|
-
|
18
|
+
"Mock Transport"
|
21
19
|
end
|
22
20
|
|
23
21
|
private
|
24
22
|
|
25
23
|
def trace_calls
|
26
24
|
interface_methods = {
|
27
|
-
|
25
|
+
"Train::Transports::Mock" =>
|
28
26
|
Train::Transports::Mock.instance_methods(false),
|
29
|
-
|
27
|
+
"Train::Transports::Mock::Connection" =>
|
30
28
|
Connection.instance_methods(false),
|
31
|
-
|
29
|
+
"Train::Transports::Mock::Connection::File" =>
|
32
30
|
Connection::FileCommon.instance_methods(false),
|
33
|
-
|
31
|
+
"Train::Transports::Mock::Connection::OS" =>
|
34
32
|
Train::Platform.instance_methods(false),
|
35
33
|
}
|
36
34
|
|
37
35
|
# rubocop:disable Metrics/ParameterLists
|
38
36
|
# rubocop:disable Lint/Eval
|
39
|
-
set_trace_func
|
40
|
-
unless classname.to_s.start_with?(
|
41
|
-
|
42
|
-
|
37
|
+
set_trace_func(proc { |event, _file, _line, id, binding, classname|
|
38
|
+
unless classname.to_s.start_with?("Train::Transports::Mock") &&
|
39
|
+
(event == "call") &&
|
40
|
+
interface_methods[classname.to_s].include?(id)
|
43
41
|
next
|
44
42
|
end
|
45
43
|
# kindly borrowed from the wonderful simple-tracer by matugm
|
46
44
|
arg_names = eval(
|
47
|
-
|
45
|
+
"method(__method__).parameters.map { |arg| arg[1].to_s }",
|
48
46
|
binding)
|
49
|
-
args = eval("#{arg_names}.map { |arg| eval(arg) }", binding).join(
|
50
|
-
prefix =
|
47
|
+
args = eval("#{arg_names}.map { |arg| eval(arg) }", binding).join(", ")
|
48
|
+
prefix = "-" * (classname.to_s.count(":") - 2) + "> "
|
51
49
|
puts("#{prefix}#{id} #{args}")
|
52
|
-
}
|
50
|
+
})
|
53
51
|
# rubocop:enable all
|
54
52
|
end
|
55
53
|
end
|
@@ -67,14 +65,14 @@ class Train::Transports::Mock
|
|
67
65
|
end
|
68
66
|
|
69
67
|
def uri
|
70
|
-
|
68
|
+
"mock://"
|
71
69
|
end
|
72
70
|
|
73
71
|
def mock_os(value = {})
|
74
72
|
# if a user passes a nil value, set to an empty hash so the merge still succeeds
|
75
73
|
value ||= {}
|
76
|
-
value.each { |k, v| value[k] =
|
77
|
-
value = { name:
|
74
|
+
value.each { |k, v| value[k] = "unknown" if v.nil? }
|
75
|
+
value = { name: "mock", family: "mock", release: "unknown", arch: "unknown" }.merge(value)
|
78
76
|
|
79
77
|
platform = Train::Platforms.name(value[:name])
|
80
78
|
platform.find_family_hierarchy
|
@@ -100,26 +98,26 @@ class Train::Transports::Mock
|
|
100
98
|
end
|
101
99
|
|
102
100
|
def mock_command(cmd, stdout = nil, stderr = nil, exit_status = 0)
|
103
|
-
@cache[:command][cmd] = Command.new(stdout ||
|
101
|
+
@cache[:command][cmd] = Command.new(stdout || "", stderr || "", exit_status)
|
104
102
|
end
|
105
103
|
|
106
104
|
def command_not_found(cmd)
|
107
105
|
if @options[:verbose]
|
108
|
-
|
109
|
-
|
110
|
-
|
106
|
+
$stderr.puts("Command not mocked:")
|
107
|
+
$stderr.puts(" " + cmd.to_s.split("\n").join("\n "))
|
108
|
+
$stderr.puts(" SHA: " + Digest::SHA256.hexdigest(cmd.to_s))
|
111
109
|
end
|
112
110
|
# return a non-zero exit code
|
113
111
|
mock_command(cmd, nil, nil, 1)
|
114
112
|
end
|
115
113
|
|
116
114
|
def file_not_found(path)
|
117
|
-
|
115
|
+
$stderr.puts("File not mocked: " + path.to_s) if @options[:verbose]
|
118
116
|
File.new(self, path)
|
119
117
|
end
|
120
118
|
|
121
119
|
def to_s
|
122
|
-
|
120
|
+
"Mock Connection"
|
123
121
|
end
|
124
122
|
|
125
123
|
private
|
@@ -142,23 +140,23 @@ end
|
|
142
140
|
class Train::Transports::Mock::Connection
|
143
141
|
class File < Train::File
|
144
142
|
def self.from_json(json)
|
145
|
-
res = new(json[
|
146
|
-
json[
|
147
|
-
json[
|
148
|
-
res.type = json[
|
143
|
+
res = new(json["backend"],
|
144
|
+
json["path"],
|
145
|
+
json["follow_symlink"])
|
146
|
+
res.type = json["type"]
|
149
147
|
Train::File::DATA_FIELDS.each do |f|
|
150
|
-
m = (f.tr(
|
148
|
+
m = (f.tr("?", "") + "=").to_sym
|
151
149
|
res.method(m).call(json[f])
|
152
150
|
end
|
153
151
|
res
|
154
152
|
end
|
155
153
|
|
156
154
|
Train::File::DATA_FIELDS.each do |m|
|
157
|
-
attr_accessor m.tr(
|
158
|
-
next unless m.include?(
|
155
|
+
attr_accessor m.tr("?", "").to_sym
|
156
|
+
next unless m.include?("?")
|
159
157
|
|
160
158
|
define_method m.to_sym do
|
161
|
-
method(m.tr(
|
159
|
+
method(m.tr("?", "").to_sym).call
|
162
160
|
end
|
163
161
|
end
|
164
162
|
attr_accessor :type
|