cem_acpt 0.2.5 → 0.6.1
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/.github/workflows/spec.yml +38 -0
- data/Gemfile +4 -3
- data/Gemfile.lock +85 -56
- data/README.md +144 -83
- data/cem_acpt.gemspec +8 -7
- data/exe/cem_acpt +41 -7
- data/lib/cem_acpt/config.rb +345 -0
- data/lib/cem_acpt/core_extensions.rb +17 -61
- data/lib/cem_acpt/goss/api/action_response.rb +175 -0
- data/lib/cem_acpt/goss/api.rb +83 -0
- data/lib/cem_acpt/goss.rb +8 -0
- data/lib/cem_acpt/image_name_builder.rb +0 -9
- data/lib/cem_acpt/logging/formatter.rb +97 -0
- data/lib/cem_acpt/logging.rb +168 -142
- data/lib/cem_acpt/platform/base.rb +26 -37
- data/lib/cem_acpt/platform/gcp.rb +48 -62
- data/lib/cem_acpt/platform.rb +30 -28
- data/lib/cem_acpt/provision/terraform/linux.rb +47 -0
- data/lib/cem_acpt/provision/terraform/os_data.rb +72 -0
- data/lib/cem_acpt/provision/terraform/windows.rb +22 -0
- data/lib/cem_acpt/provision/terraform.rb +193 -0
- data/lib/cem_acpt/provision.rb +20 -0
- data/lib/cem_acpt/puppet_helpers.rb +0 -1
- data/lib/cem_acpt/test_data.rb +23 -13
- data/lib/cem_acpt/test_runner/log_formatter/goss_action_response.rb +104 -0
- data/lib/cem_acpt/test_runner/log_formatter.rb +10 -0
- data/lib/cem_acpt/test_runner.rb +170 -3
- data/lib/cem_acpt/utils/puppet.rb +29 -0
- data/lib/cem_acpt/utils/ssh.rb +197 -0
- data/lib/cem_acpt/utils/terminal.rb +27 -0
- data/lib/cem_acpt/utils.rb +4 -138
- data/lib/cem_acpt/version.rb +1 -1
- data/lib/cem_acpt.rb +70 -20
- data/lib/terraform/gcp/linux/goss/puppet_idempotent.yaml +10 -0
- data/lib/terraform/gcp/linux/goss/puppet_noop.yaml +12 -0
- data/lib/terraform/gcp/linux/main.tf +191 -0
- data/lib/terraform/gcp/linux/systemd/goss-acpt.service +8 -0
- data/lib/terraform/gcp/linux/systemd/goss-idempotent.service +8 -0
- data/lib/terraform/gcp/linux/systemd/goss-noop.service +8 -0
- data/lib/terraform/gcp/windows/.keep +0 -0
- data/sample_config.yaml +22 -21
- metadata +88 -56
- data/lib/cem_acpt/bootstrap/bootstrapper.rb +0 -206
- data/lib/cem_acpt/bootstrap/operating_system/rhel_family.rb +0 -129
- data/lib/cem_acpt/bootstrap/operating_system.rb +0 -17
- data/lib/cem_acpt/bootstrap.rb +0 -12
- data/lib/cem_acpt/context.rb +0 -153
- data/lib/cem_acpt/platform/base/cmd.rb +0 -71
- data/lib/cem_acpt/platform/gcp/cmd.rb +0 -345
- data/lib/cem_acpt/platform/gcp/compute.rb +0 -332
- data/lib/cem_acpt/platform/vmpooler.rb +0 -24
- data/lib/cem_acpt/rspec_utils.rb +0 -242
- data/lib/cem_acpt/shared_objects.rb +0 -537
- data/lib/cem_acpt/spec_helper_acceptance.rb +0 -184
- data/lib/cem_acpt/test_runner/run_handler.rb +0 -187
- data/lib/cem_acpt/test_runner/runner.rb +0 -210
- data/lib/cem_acpt/test_runner/runner_result.rb +0 -103
@@ -41,13 +41,8 @@ module CemAcpt
|
|
41
41
|
# @param test_data [Hash] The test data to use to build the image name.
|
42
42
|
# @return [String] The image name.
|
43
43
|
def build(test_data)
|
44
|
-
logger.debug 'Building image name...'
|
45
|
-
logger.debug "Using config: #{@config.to_h}"
|
46
|
-
logger.debug "Test data: #{test_data}"
|
47
44
|
parts = resolve_parts(test_data)
|
48
|
-
logger.debug "Resolved parts: #{parts}"
|
49
45
|
image_name = create_image_name(parts)
|
50
|
-
logger.debug "Created image name: #{image_name}"
|
51
46
|
final_image_name = character_substitutions(image_name)
|
52
47
|
logger.debug "Final image name: #{final_image_name}"
|
53
48
|
final_image_name
|
@@ -61,10 +56,8 @@ module CemAcpt
|
|
61
56
|
# @return [Array] The parts array with variables resolved.
|
62
57
|
def resolve_parts(test_data)
|
63
58
|
@config[:parts].each_with_object([]) do |part, ary|
|
64
|
-
logger.debug "Resolving part: #{part}"
|
65
59
|
if part.start_with?('$')
|
66
60
|
var_path = part[1..-1]
|
67
|
-
logger.debug "Resolving variable path: #{var_path}"
|
68
61
|
ary << test_data.dot_dig(var_path)
|
69
62
|
else
|
70
63
|
ary << part
|
@@ -77,10 +70,8 @@ module CemAcpt
|
|
77
70
|
# @return [String] The image name.
|
78
71
|
def create_image_name(parts)
|
79
72
|
image_name = @config[:join_with] ? parts.join(@config[:join_with]) : parts.join
|
80
|
-
logger.debug("Final image name: #{image_name}")
|
81
73
|
|
82
74
|
if @config[:validation_pattern]
|
83
|
-
logger.debug "Validating image name: #{image_name}..."
|
84
75
|
return image_name if image_name.match?(@config[:validation_pattern])
|
85
76
|
|
86
77
|
raise "Image name #{image_name} does not match validation pattern #{@config[:validation_pattern]}"
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CemAcpt
|
4
|
+
module Logging
|
5
|
+
module Formatter
|
6
|
+
class << self
|
7
|
+
def valid_format?(log_format)
|
8
|
+
all.any? { |f| f.log_format == log_format.downcase.to_sym }
|
9
|
+
end
|
10
|
+
|
11
|
+
def for(log_format)
|
12
|
+
formatter = all.find { |f| f.log_format == log_format.downcase.to_sym }
|
13
|
+
raise "Unknown log format: #{log_format}" unless formatter
|
14
|
+
|
15
|
+
formatter.get
|
16
|
+
end
|
17
|
+
|
18
|
+
def all
|
19
|
+
@all ||= [FileFormatter.new, JSONFormatter.new, TextFormatter.new, GithubActionFormatter.new]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class FileFormatter
|
24
|
+
attr_reader :log_format
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@log_format = :file
|
28
|
+
end
|
29
|
+
|
30
|
+
def get
|
31
|
+
proc do |severity, datetime, progname, msg|
|
32
|
+
format(severity, datetime, progname, msg)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def format(severity, datetime, progname, msg)
|
39
|
+
"[#{datetime}] #{severity}: #{progname}: #{msg}\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class JSONFormatter < FileFormatter
|
44
|
+
def initialize
|
45
|
+
super
|
46
|
+
@log_format = :json
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def format(severity, datetime, progname, msg)
|
52
|
+
require 'json'
|
53
|
+
{
|
54
|
+
timestamp: datetime,
|
55
|
+
progname: progname,
|
56
|
+
severity: severity,
|
57
|
+
message: msg,
|
58
|
+
}.to_json + "\n"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class TextFormatter < FileFormatter
|
63
|
+
def initialize
|
64
|
+
super
|
65
|
+
@log_format = :text
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def format(severity, _datetime, progname, msg)
|
71
|
+
"#{severity}: #{progname}: #{msg}\n"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class GithubActionFormatter < FileFormatter
|
76
|
+
SEV_MAP = {
|
77
|
+
'DEBUG' => '::debug::',
|
78
|
+
'INFO' => '::notice::',
|
79
|
+
'WARN' => '::warning::',
|
80
|
+
'ERROR' => '::error::',
|
81
|
+
'FATAL' => '::error::',
|
82
|
+
}.freeze
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
super
|
86
|
+
@log_format = :github_action
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def format(severity, _datetime, progname, msg)
|
92
|
+
"#{SEV_MAP[severity]}[#{progname}] #{msg}\n"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/cem_acpt/logging.rb
CHANGED
@@ -1,27 +1,50 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'logger'
|
4
|
+
require 'cem_acpt/logging/formatter'
|
4
5
|
|
5
6
|
module CemAcpt
|
6
7
|
# Logging for CemAcpt
|
7
8
|
module Logging
|
8
9
|
LEVEL_MAP = {
|
9
|
-
'debug' => Logger::DEBUG,
|
10
|
-
'info' => Logger::INFO,
|
11
|
-
'warn' => Logger::WARN,
|
12
|
-
'error' => Logger::ERROR,
|
13
|
-
'fatal' => Logger::FATAL,
|
14
|
-
'unknown' => Logger::UNKNOWN,
|
10
|
+
'debug' => ::Logger::DEBUG,
|
11
|
+
'info' => ::Logger::INFO,
|
12
|
+
'warn' => ::Logger::WARN,
|
13
|
+
'error' => ::Logger::ERROR,
|
14
|
+
'fatal' => ::Logger::FATAL,
|
15
|
+
'unknown' => ::Logger::UNKNOWN,
|
15
16
|
}
|
16
17
|
|
17
18
|
# Delegator class for when you want to log to multiple devices
|
18
19
|
# at the same time, such as STDOUT and a file.
|
19
|
-
# @param loggers [
|
20
|
+
# @param loggers [Logger] one or more instances of CemAcpt::Logging::Logger
|
20
21
|
class MultiLogger
|
22
|
+
# @param configs [Array<Hash>] an array of hashes containing the
|
23
|
+
# configuration for each logger. Each hash must contain the keys
|
24
|
+
# :logdev, :shift_age, and :shift_size. The values for these keys
|
25
|
+
# are passed to the Logger.new method. Any other keys and values
|
26
|
+
# are passed to the Logger.new method as keyword arguments.
|
27
|
+
# @return [MultiLogger] a new instance of MultiLogger
|
28
|
+
def self.from_logger_configs(configs)
|
29
|
+
return if configs.nil? || configs.empty?
|
30
|
+
|
31
|
+
loggers = configs.map do |config|
|
32
|
+
CemAcpt::Logging::Logger.new(config[:logdev],
|
33
|
+
config[:shift_age],
|
34
|
+
config[:shift_size],
|
35
|
+
**config.except(:logdev, :shift_age, :shift_size))
|
36
|
+
end
|
37
|
+
new(*loggers)
|
38
|
+
end
|
39
|
+
|
21
40
|
def initialize(*loggers)
|
22
41
|
@loggers = loggers
|
23
42
|
end
|
24
43
|
|
44
|
+
def logger_configs
|
45
|
+
@loggers.map(&:config_hash)
|
46
|
+
end
|
47
|
+
|
25
48
|
def method_missing(m, *args, &block)
|
26
49
|
if @loggers.all? { |l| l.respond_to?(m) }
|
27
50
|
@loggers.map { |l| l.send(m, *args, &block) }
|
@@ -35,6 +58,137 @@ module CemAcpt
|
|
35
58
|
end
|
36
59
|
end
|
37
60
|
|
61
|
+
# Delagator class for the standard Ruby Logger class.
|
62
|
+
# This class is used to ensure the Github Actions formatter
|
63
|
+
# correctly formats the log output when using the standard
|
64
|
+
# Ruby Logger class methods such as #info, #debug, etc.
|
65
|
+
class Logger < ::Logger
|
66
|
+
attr_reader :config_hash
|
67
|
+
attr_accessor :trap_context
|
68
|
+
|
69
|
+
def initialize(logdev, shift_age = 0, shift_size = 1_048_576, **kwargs)
|
70
|
+
@config_hash = { logdev: logdev, shift_age: shift_age, shift_size: shift_size, **kwargs }
|
71
|
+
@ci_mode = (kwargs[:formatter].downcase.to_sym == :github_action || !ENV['GITHUB_ACTIONS'].nil? || !ENV['CI'].nil?)
|
72
|
+
kwargs[:formatter] = CemAcpt::Logging::Formatter.for(kwargs[:formatter]) if kwargs[:formatter]
|
73
|
+
super(logdev, shift_age, shift_size, **kwargs)
|
74
|
+
@raw_logdev = logdev # Used for logging from trap context
|
75
|
+
@trap_context = false # If true, will not use the standard Logger methods and will write directly to the logdev
|
76
|
+
@verbose = false
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_verbose(value)
|
80
|
+
raise ArgumentError, 'value must be a boolean' unless [true, false].include?(value)
|
81
|
+
|
82
|
+
@verbose = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def verbose(progname = nil, &block)
|
86
|
+
return unless @verbose
|
87
|
+
|
88
|
+
debug(progname, &block)
|
89
|
+
end
|
90
|
+
|
91
|
+
def debug(progname = nil, &block)
|
92
|
+
return if log_trap_context('debug', progname, &block)
|
93
|
+
return if log_ci_mode('debug', progname, &block)
|
94
|
+
|
95
|
+
super
|
96
|
+
end
|
97
|
+
|
98
|
+
def info(progname = nil, &block)
|
99
|
+
return if log_trap_context('info', progname, &block)
|
100
|
+
return if log_ci_mode('info', progname, &block)
|
101
|
+
|
102
|
+
super
|
103
|
+
end
|
104
|
+
|
105
|
+
def warn(progname = nil, &block)
|
106
|
+
return if log_trap_context('warn', progname, &block)
|
107
|
+
return if log_ci_mode('warn', progname, &block)
|
108
|
+
|
109
|
+
super
|
110
|
+
end
|
111
|
+
|
112
|
+
def error(progname = nil, &block)
|
113
|
+
return if log_trap_context('error', progname, &block)
|
114
|
+
return if log_ci_mode('error', progname, &block)
|
115
|
+
|
116
|
+
super
|
117
|
+
end
|
118
|
+
|
119
|
+
def fatal(progname = nil, &block)
|
120
|
+
return if log_trap_context('fatal', progname, &block)
|
121
|
+
return if log_ci_mode('fatal', progname, &block)
|
122
|
+
|
123
|
+
super
|
124
|
+
end
|
125
|
+
|
126
|
+
# Wraps the given block in a Github Actions group if in CI mode
|
127
|
+
# @param name [String] the name of the group
|
128
|
+
def with_ci_group(name)
|
129
|
+
return yield unless @ci_mode
|
130
|
+
|
131
|
+
self.<< "::group::#{name}\n"
|
132
|
+
yield
|
133
|
+
ensure
|
134
|
+
self.<< "::endgroup::\n" if @ci_mode
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
# Can't use the standard Logger methods when in trap context
|
140
|
+
# because they don't work. So we have to write directly to the
|
141
|
+
# raw logdev. Unlike the standard Logger methods, there is no
|
142
|
+
# Mutex lock, so messages are not guaranteed to be in order.
|
143
|
+
# This is necessary in the trap context because using a Mutex
|
144
|
+
# lock in a trap context will cause a deadlock.
|
145
|
+
def log_trap_context(severity, progname = nil, &block)
|
146
|
+
return false unless @trap_context && level <= LEVEL_MAP[severity]
|
147
|
+
|
148
|
+
if @raw_logdev.respond_to?(:puts)
|
149
|
+
@raw_logdev.puts(ci_format(severity, false, progname, &block))
|
150
|
+
elsif @raw_logdev.respond_to?(:write)
|
151
|
+
@raw_logdev.write(ci_format(severity, true, progname, &block))
|
152
|
+
else
|
153
|
+
# Default to logging to STDERR
|
154
|
+
$stderr.puts(ci_format(severity, false, progname, &block))
|
155
|
+
end
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
# CI mode uses << instead of the standard Logger methods
|
160
|
+
# because Github Actions wants messages to be echoed. This
|
161
|
+
# is a way to ensure that, in the event of using a multi-logger
|
162
|
+
# with a standard Logger, the CI mode messages are still
|
163
|
+
# formatted correctly.
|
164
|
+
def log_ci_mode(severity, progname = nil, &block)
|
165
|
+
return false unless @ci_mode && level <= LEVEL_MAP[severity]
|
166
|
+
|
167
|
+
self.<<(ci_format(severity, true, progname, &block))
|
168
|
+
true
|
169
|
+
end
|
170
|
+
|
171
|
+
# Formats the log message for CI mode, translating the severity
|
172
|
+
# level to the correct format for Github Actions and adding
|
173
|
+
# the colon separators.
|
174
|
+
def ci_format(severity, newline = true, progname = nil, &block)
|
175
|
+
sev = if severity == 'fatal'
|
176
|
+
'error'
|
177
|
+
elsif severity == 'warn'
|
178
|
+
'warning'
|
179
|
+
elsif severity == 'info'
|
180
|
+
'notice'
|
181
|
+
else
|
182
|
+
severity
|
183
|
+
end
|
184
|
+
block_message = block_given? ? block.call : nil
|
185
|
+
base = [progname, block_message].compact.join(': ')
|
186
|
+
return if base.empty?
|
187
|
+
|
188
|
+
newline ? "::#{sev}::#{base}\n" : "::#{sev}::#{base}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
38
192
|
class << self
|
39
193
|
def new_logger(*logdevs, **configs)
|
40
194
|
new_configs = current_log_config.merge(configs.reject { |_, v| v.nil? })
|
@@ -57,14 +211,9 @@ module CemAcpt
|
|
57
211
|
|
58
212
|
# Exposes a logger instance. Will either use the currently set logger or
|
59
213
|
# create a new one.
|
60
|
-
# @return [
|
214
|
+
# @return [MultiLogger]
|
61
215
|
def logger
|
62
|
-
@logger ||=
|
63
|
-
current_log_config[:logdev],
|
64
|
-
current_log_config[:shift_age],
|
65
|
-
current_log_config[:shift_size],
|
66
|
-
**current_log_config.reject { |k, _| %i[logdev shift_age shift_size].include?(k) }
|
67
|
-
)
|
216
|
+
@logger ||= new_logger($stdout)
|
68
217
|
end
|
69
218
|
|
70
219
|
# Shortcut method for logger.level
|
@@ -92,41 +241,7 @@ module CemAcpt
|
|
92
241
|
# @param f [Symbol] the log format style to set
|
93
242
|
# @return [Proc] the proc to be passed to Logger#formatter=
|
94
243
|
def new_log_formatter(f)
|
95
|
-
|
96
|
-
when :json
|
97
|
-
require 'json'
|
98
|
-
@current_log_format = :json
|
99
|
-
proc do |severity, datetime, progname, msg|
|
100
|
-
{
|
101
|
-
timestamp: datetime,
|
102
|
-
progname: progname,
|
103
|
-
severity: severity,
|
104
|
-
message: msg,
|
105
|
-
}.to_json + "\n"
|
106
|
-
end
|
107
|
-
when :text
|
108
|
-
@current_log_format = :text
|
109
|
-
proc do |severity, _datetime, _progname, msg|
|
110
|
-
"#{severity} - #{msg}\n"
|
111
|
-
end
|
112
|
-
when :github_action
|
113
|
-
@current_log_format = :github_action
|
114
|
-
sev_map = {
|
115
|
-
'DEBUG' => '::debug::',
|
116
|
-
'INFO' => '::notice::',
|
117
|
-
'WARN' => '::warning::',
|
118
|
-
'ERROR' => '::error::',
|
119
|
-
'FATAL' => '::error::',
|
120
|
-
}
|
121
|
-
proc do |severity, _datetime, _progname, msg|
|
122
|
-
"#{sev_map[severity]}{#{msg}}\n"
|
123
|
-
end
|
124
|
-
else
|
125
|
-
@current_log_format = :file
|
126
|
-
proc do |severity, datetime, _progname, msg|
|
127
|
-
"[#{datetime}] #{severity}: #{msg}\n"
|
128
|
-
end
|
129
|
-
end
|
244
|
+
CemAcpt::Logging::Formatter.for(f)
|
130
245
|
end
|
131
246
|
|
132
247
|
# Returns the current log config if set, or the default if not.
|
@@ -134,15 +249,14 @@ module CemAcpt
|
|
134
249
|
def current_log_config
|
135
250
|
return @log_config if @log_config
|
136
251
|
|
137
|
-
formatter = new_log_formatter(current_log_format)
|
138
252
|
@log_config = {
|
139
253
|
logdev: $stdout,
|
140
254
|
shift_age: 'o',
|
141
255
|
shift_size: 1_048_576,
|
142
|
-
level: Logger::INFO,
|
256
|
+
level: ::Logger::INFO,
|
143
257
|
progname: 'CemAcpt',
|
144
258
|
datetime_format: '%Y%m%dT%H%M%S%z',
|
145
|
-
formatter:
|
259
|
+
formatter: current_log_format,
|
146
260
|
}
|
147
261
|
@log_config
|
148
262
|
end
|
@@ -177,12 +291,12 @@ module CemAcpt
|
|
177
291
|
@log_config[:logdev] = $stdout
|
178
292
|
logger.warn("Unknown log target: #{logdev.inspect}, using STDOUT")
|
179
293
|
end
|
180
|
-
@logger = Logger.new(
|
294
|
+
@logger = MultiLogger.new(Logger.new(
|
181
295
|
@log_config[:logdev],
|
182
296
|
@log_config[:shift_age],
|
183
297
|
@log_config[:shift_size],
|
184
298
|
**@log_config.reject { |k, _| %i[logdev shift_age shift_size].include?(k) },
|
185
|
-
)
|
299
|
+
))
|
186
300
|
end
|
187
301
|
end
|
188
302
|
|
@@ -260,92 +374,4 @@ module CemAcpt
|
|
260
374
|
CemAcpt::Logging.new_log_config(logdev: logdev, shift_age: shift_age, shift_size: shift_size, level: level, formatter: formatter, datetime_format: datetime_format)
|
261
375
|
end
|
262
376
|
end
|
263
|
-
|
264
|
-
module LoggingAsync
|
265
|
-
require 'concurrent-ruby'
|
266
|
-
|
267
|
-
class << self
|
268
|
-
def log_write_thread
|
269
|
-
@log_write_thread ||= Concurrent::SingleThreadExecutor.new
|
270
|
-
end
|
271
|
-
|
272
|
-
def async_debug(message, prefix = nil)
|
273
|
-
msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
|
274
|
-
CemAcpt::Logging.logger.debug(msg)
|
275
|
-
end
|
276
|
-
|
277
|
-
def async_info(message, prefix = nil)
|
278
|
-
msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
|
279
|
-
CemAcpt::Logging.logger.info(msg)
|
280
|
-
end
|
281
|
-
|
282
|
-
def async_warn(message, prefix = nil)
|
283
|
-
msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
|
284
|
-
CemAcpt::Logging.logger.warn(msg)
|
285
|
-
end
|
286
|
-
|
287
|
-
def async_error(message, prefix = nil)
|
288
|
-
msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
|
289
|
-
CemAcpt::Logging.logger.error(msg)
|
290
|
-
end
|
291
|
-
|
292
|
-
def async_fatal(message, prefix = nil)
|
293
|
-
msg = prefix.nil? || prefix.empty? ? message : "#{prefix} #{message}"
|
294
|
-
CemAcpt::Logging.logger.fatal(msg)
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
# Provides class method wrappers for logging methods
|
299
|
-
def self.included(base)
|
300
|
-
class << base
|
301
|
-
def log_write_thread
|
302
|
-
CemAcpt::LoggingAsync.log_write_thread
|
303
|
-
end
|
304
|
-
|
305
|
-
def async_debug(message, prefix = nil)
|
306
|
-
CemAcpt::LoggingAsync.async_debug(message, prefix)
|
307
|
-
end
|
308
|
-
|
309
|
-
def async_info(message, prefix = nil)
|
310
|
-
CemAcpt::LoggingAsync.async_info(message, prefix)
|
311
|
-
end
|
312
|
-
|
313
|
-
def async_warn(message, prefix = nil)
|
314
|
-
CemAcpt::LoggingAsync.async_warn(message, prefix)
|
315
|
-
end
|
316
|
-
|
317
|
-
def async_error(message, prefix = nil)
|
318
|
-
CemAcpt::LoggingAsync.async_error(message, prefix)
|
319
|
-
end
|
320
|
-
|
321
|
-
def async_fatal(message, prefix = nil)
|
322
|
-
CemAcpt::LoggingAsync.async_fatal(message, prefix)
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
def log_write_thread
|
328
|
-
CemAcpt::LoggingAsync.log_write_thread
|
329
|
-
end
|
330
|
-
|
331
|
-
def async_debug(message, prefix = nil)
|
332
|
-
CemAcpt::LoggingAsync.async_debug(message, prefix)
|
333
|
-
end
|
334
|
-
|
335
|
-
def async_info(message, prefix = nil)
|
336
|
-
CemAcpt::LoggingAsync.async_info(message, prefix)
|
337
|
-
end
|
338
|
-
|
339
|
-
def async_warn(message, prefix = nil)
|
340
|
-
CemAcpt::LoggingAsync.async_warn(message, prefix)
|
341
|
-
end
|
342
|
-
|
343
|
-
def async_error(message, prefix = nil)
|
344
|
-
CemAcpt::LoggingAsync.async_error(message, prefix)
|
345
|
-
end
|
346
|
-
|
347
|
-
def async_fatal(message, prefix = nil)
|
348
|
-
CemAcpt::LoggingAsync.async_fatal(message, prefix)
|
349
|
-
end
|
350
|
-
end
|
351
377
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
3
4
|
require 'securerandom'
|
4
5
|
require_relative File.join(__dir__, '..', 'image_name_builder')
|
5
6
|
require_relative File.join(__dir__, '..', 'logging')
|
@@ -10,69 +11,57 @@ module CemAcpt::Platform
|
|
10
11
|
class Base
|
11
12
|
include CemAcpt::Logging
|
12
13
|
|
13
|
-
attr_reader :
|
14
|
+
attr_reader :test_data, :node_name
|
14
15
|
|
15
16
|
# @param conf [CemAcpt::Config] the config object.
|
16
17
|
# @param single_test_data [Hash] the test data for the current test.
|
17
|
-
|
18
|
-
def initialize(conf, single_test_data, local_port)
|
18
|
+
def initialize(config, single_test_data)
|
19
19
|
raise ArgumentError, 'single_test_data must be a Hash' unless single_test_data.is_a?(Hash)
|
20
20
|
|
21
|
-
@config =
|
21
|
+
@config = config
|
22
22
|
@test_data = single_test_data
|
23
|
-
@local_port = local_port
|
24
23
|
@node_name = @test_data[:node_name] || random_node_name
|
25
|
-
@image_name = conf.has?('image_name_builder') ? image_name_builder(conf, single_test_data) : @test_data[:image_name]
|
26
24
|
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
node_name: node_name,
|
29
|
+
image_name: image_name,
|
30
|
+
test_data: test_data,
|
31
|
+
platform_data: platform_data,
|
32
|
+
node_data: node_data,
|
33
|
+
}
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
raise NotImplementedError, '#provision must be implemented by subclass'
|
36
|
+
def to_json(*args)
|
37
|
+
to_h.to_json(*args)
|
36
38
|
end
|
37
39
|
|
38
|
-
#
|
39
|
-
def
|
40
|
-
raise NotImplementedError, '
|
40
|
+
# Data common to all nodes of the same platform.
|
41
|
+
def platform_data
|
42
|
+
raise NotImplementedError, 'common_data must be implemented by the specific platform module'
|
41
43
|
end
|
42
44
|
|
43
|
-
#
|
44
|
-
def
|
45
|
-
raise NotImplementedError, '
|
45
|
+
# Data specific to the current node.
|
46
|
+
def node_data
|
47
|
+
raise NotImplementedError, 'node_data must be implemented by the specific platform module'
|
46
48
|
end
|
47
49
|
|
48
|
-
#
|
49
|
-
def
|
50
|
-
|
50
|
+
# Generates or retrieves an image name from the test data.
|
51
|
+
def image_name
|
52
|
+
@image_name ||= (@config.has?('image_name_builder') ? image_name_builder(@config, test_data) : test_data[:image_name])
|
51
53
|
end
|
52
54
|
|
55
|
+
private
|
56
|
+
|
53
57
|
# Generates a random node name.
|
54
58
|
def random_node_name
|
55
|
-
"acpt
|
59
|
+
"cem-acpt-#{SecureRandom.hex(12)}"
|
56
60
|
end
|
57
61
|
|
58
62
|
# Builds an image name if the config specifies to use the image name builder.
|
59
63
|
def image_name_builder(conf, tdata)
|
60
64
|
@image_name_builder ||= CemAcpt::ImageNameBuilder.new(conf).build(tdata)
|
61
65
|
end
|
62
|
-
|
63
|
-
# Returns a command provider specified by the Platform module of the specific platform.
|
64
|
-
def self.command_provider
|
65
|
-
raise NotImplementedError, '#command_provider must be implemented by subclass'
|
66
|
-
end
|
67
|
-
|
68
|
-
# Applies a Puppet manifest on the given node.
|
69
|
-
def self.apply_manifest(_instance_name, _manifest, _opts = {})
|
70
|
-
raise NotImplementedError, '#apply_manifest must be implemented by subclass'
|
71
|
-
end
|
72
|
-
|
73
|
-
# Runs a shell command on the given node.
|
74
|
-
def self.run_shell(_instance_name, _cmd, _opts = {})
|
75
|
-
raise NotImplementedError, '#run_shell must be implemented by subclass'
|
76
|
-
end
|
77
66
|
end
|
78
67
|
end
|