1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
require_relative "../plugins"
require "digest"
module Train::Transports
class Mock < Train.plugin(1)
name "mock"
def initialize(conf = nil)
@conf = conf || {}
trace_calls if @conf[:trace]
end
def connection
@connection ||= Connection.new(@conf)
end
def to_s
"Mock Transport"
end
private
def trace_calls
interface_methods = {
"Train::Transports::Mock" =>
Train::Transports::Mock.instance_methods(false),
"Train::Transports::Mock::Connection" =>
Connection.instance_methods(false),
"Train::Transports::Mock::Connection::File" =>
Connection::FileCommon.instance_methods(false),
"Train::Transports::Mock::Connection::OS" =>
Train::Platform.instance_methods(false),
}
# rubocop:disable Metrics/ParameterLists
# rubocop:disable Security/Eval
set_trace_func(proc { |event, _file, _line, id, binding, classname|
unless classname.to_s.start_with?("Train::Transports::Mock") &&
(event == "call") &&
interface_methods[classname.to_s].include?(id)
next
end
# kindly borrowed from the wonderful simple-tracer by matugm
arg_names = eval(
"method(__method__).parameters.map { |arg| arg[1].to_s }",
binding
)
args = eval("#{arg_names}.map { |arg| eval(arg) }", binding).join(", ")
prefix = "-" * (classname.to_s.count(":") - 2) + "> "
puts("#{prefix}#{id} #{args}")
})
# rubocop:enable all
end
end
end
class Train::Transports::Mock
class Connection < BaseConnection
attr_reader :options
def initialize(conf = nil)
super(conf)
mock_os
enable_cache(:file)
enable_cache(:command)
end
def uri
"mock://"
end
DEFAULTS = {
name: "mock",
family: "mock",
release: "unknown",
arch: "unknown",
}.freeze
def mock_os(value = {})
value = DEFAULTS
.merge(value || {})
.transform_values { |v| v || "unknown" }
platform = Train::Platforms.name(value[:name])
platform.find_family_hierarchy
platform.platform = value
platform.add_platform_methods
@platform = platform
end
def commands=(commands)
@cache[:command] = commands
end
def commands
@cache[:command]
end
def files=(files)
@cache[:file] = files
end
def files
@cache[:file]
end
def mock_command(cmd, stdout = nil, stderr = nil, exit_status = 0)
@cache[:command][cmd] = Command.new(stdout || "", stderr || "", exit_status)
end
def command_not_found(cmd)
if @options[:verbose]
$stderr.puts("Command not mocked:")
$stderr.puts(" " + cmd.to_s.split("\n").join("\n "))
$stderr.puts(" SHA: " + Digest::SHA256.hexdigest(cmd.to_s))
end
# return a non-zero exit code
mock_command(cmd, nil, nil, 1)
end
def file_not_found(path)
$stderr.puts("File not mocked: " + path.to_s) if @options[:verbose]
File.new(self, path)
end
def to_s
"Mock Connection"
end
private
def run_command_via_connection(cmd, &_data_handler)
@cache[:command][Digest::SHA256.hexdigest cmd.to_s] ||
command_not_found(cmd)
end
def file_via_connection(path)
file_not_found(path)
end
end
end
class Train::Transports::Mock::Connection
Command = Struct.new(:stdout, :stderr, :exit_status)
end
class Train::Transports::Mock::Connection
class File < Train::File
def self.from_json(json)
res = new(json["backend"],
json["path"],
json["follow_symlink"])
res.type = json["type"]
Train::File::DATA_FIELDS.each do |f|
m = (f.tr("?", "") + "=").to_sym
res.method(m).call(json[f])
end
res
end
Train::File::DATA_FIELDS.each do |m|
attr_accessor m.tr("?", "").to_sym
next unless m.include?("?")
define_method m.to_sym do
method(m.tr("?", "").to_sym).call
end
end
attr_accessor :type
def initialize(backend, path, follow_symlink = true)
super(backend, path, follow_symlink)
@type = :unknown
@exist = false
end
def mounted
@mounted ||=
@backend.run_command("mount | grep -- ' on #{@path}'")
end
end
end
|