Class: BoltSpec::Plans::MockExecutor
- Inherits:
-
Object
- Object
- BoltSpec::Plans::MockExecutor
- Defined in:
- lib/bolt_spec/plans/mock_executor.rb
Overview
Nothing on the executor is ‘public’
Instance Attribute Summary collapse
-
#error_message ⇒ Object
readonly
Returns the value of attribute error_message.
-
#execute_any_plan ⇒ Object
Returns the value of attribute execute_any_plan.
-
#future ⇒ Object
readonly
Returns the value of attribute future.
-
#noop ⇒ Object
readonly
Returns the value of attribute noop.
-
#run_as ⇒ Object
Returns the value of attribute run_as.
-
#transport_features ⇒ Object
Returns the value of attribute transport_features.
-
#transports ⇒ Object
readonly
Returns the value of attribute transports.
Instance Method Summary collapse
- #assert_call_expectations ⇒ Object
- #await_results(promises) ⇒ Object
-
#batch_execute(_targets) ⇒ Object
Public methods on Bolt::Executor that need to be mocked so there aren’t “undefined method” errors.
- #create_future(plan_id:, scope: nil, name: nil) ⇒ Object
- #download_file(targets, source, destination, options = {}, _position = []) ⇒ Object
- #finish_plan(_plan_result) ⇒ Object
- #get_current_future(fiber) ⇒ Object
- #get_current_plan_id(fiber) ⇒ Object
- #get_futures_for_plan(plan_id:) ⇒ Object
- #handle_event(_event) ⇒ Object
- #in_parallel? ⇒ Boolean
-
#initialize(modulepath) ⇒ MockExecutor
constructor
A new instance of MockExecutor.
- #log_action(*_args) ⇒ Object
- #log_plan(_plan_name) ⇒ Object
- #module_file_id(file) ⇒ Object
-
#plan_complete? ⇒ Boolean
Since Futures are executed immediately once created, this will always be true by the time it’s called.
- #prompt(_prompt, _options) ⇒ Object
- #publish_event(event) ⇒ Object
- #queue_execute(targets) ⇒ Object
- #report_apply(_statements, _resources) ⇒ Object
- #report_bundled_content(_mode, _name) ⇒ Object
- #report_file_source(_plan_function, _source) ⇒ Object
- #report_function_call(_function) ⇒ Object
- #report_noop_mode(_mode) ⇒ Object
- #report_yaml_plan(_plan) ⇒ Object
- #round_robin ⇒ Object
- #run_command(targets, command, options = {}, _position = []) ⇒ Object
-
#run_in_thread ⇒ Object
Parallel function mocking.
- #run_plan(scope, plan_clj, params) ⇒ Object
- #run_script(targets, script_path, arguments, options = {}, _position = []) ⇒ Object
- #run_task(targets, task, arguments, options = {}, _position = []) ⇒ Object
- #run_task_with(target_mapping, task, options = {}, _position = []) ⇒ Object
- #shutdown ⇒ Object
- #start_plan(_plan_context) ⇒ Object
- #stub_apply ⇒ Object
- #stub_out_message ⇒ Object
- #stub_out_verbose ⇒ Object
- #subscribe(_subscriber, _types = nil) ⇒ Object
-
#transport(_protocol) ⇒ Object
Mocked for apply_prep.
- #unsubscribe(_subscriber, _types = nil) ⇒ Object
- #upload_file(targets, source_path, destination, options = {}, _position = []) ⇒ Object
- #wait(futures, **_kwargs) ⇒ Object
- #wait_until_available(targets, _options) ⇒ Object
-
#with_node_logging(_description, targets) ⇒ Object
Mocked for Apply so it does not compile and execute.
- #with_plan_allowed_exec(plan_name, params) ⇒ Object
- #without_default_logging ⇒ Object
Constructor Details
#initialize(modulepath) ⇒ MockExecutor
Returns a new instance of MockExecutor.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 23 def initialize(modulepath) @noop = false @run_as = nil @future = {} @error_message = nil @allow_apply = false @modulepath = [modulepath].flatten.map { |path| File.absolute_path(path) } MOCKED_ACTIONS.each { |action| instance_variable_set(:"@#{action}_doubles", {}) } @stub_out_message = nil @stub_out_verbose = nil @transport_features = ['puppet-agent'] @executor_real = Bolt::Executor.new # by default, we want to execute any plan that we come across without error # or mocking. users can toggle this behavior so that plans will either need to # be mocked out, or an error will be thrown. @execute_any_plan = true # plans that are allowed to be executed by the @executor_real @allowed_exec_plans = {} @id = 0 @plan_futures = [] end |
Instance Attribute Details
#error_message ⇒ Object (readonly)
Returns the value of attribute error_message.
20 21 22 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 20 def @error_message end |
#execute_any_plan ⇒ Object
Returns the value of attribute execute_any_plan.
21 22 23 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 21 def execute_any_plan @execute_any_plan end |
#future ⇒ Object (readonly)
Returns the value of attribute future.
20 21 22 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 20 def future @future end |
#noop ⇒ Object (readonly)
Returns the value of attribute noop.
20 21 22 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 20 def noop @noop end |
#run_as ⇒ Object
Returns the value of attribute run_as.
21 22 23 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 21 def run_as @run_as end |
#transport_features ⇒ Object
Returns the value of attribute transport_features.
21 22 23 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 21 def transport_features @transport_features end |
#transports ⇒ Object (readonly)
Returns the value of attribute transports.
20 21 22 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 20 def transports @transports end |
Instance Method Details
#assert_call_expectations ⇒ Object
185 186 187 188 189 190 191 192 193 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 185 def assert_call_expectations MOCKED_ACTIONS.each do |action| instance_variable_get(:"@#{action}_doubles").map do |object, doub| doub.assert_called(object) end end @stub_out_message.assert_called('out::message') if @stub_out_message @stub_out_verbose.assert_called('out::verbose') if @stub_out_verbose end |
#await_results(promises) ⇒ Object
257 258 259 260 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 257 def await_results(promises) raise "Unexpected call to apply(#{targets})" unless @allow_apply Bolt::ResultSet.new(promises.map { |target| Bolt::ApplyResult.new(target) }) end |
#batch_execute(_targets) ⇒ Object
Public methods on Bolt::Executor that need to be mocked so there aren’t “undefined method” errors.
330 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 330 def batch_execute(_targets); end |
#create_future(plan_id:, scope: nil, name: nil) ⇒ Object
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 284 def create_future(plan_id:, scope: nil, name: nil) newscope = nil if scope # Create the new scope newscope = Puppet::Parser::Scope.new(scope.compiler) local = Puppet::Parser::Scope::LocalScope.new # Compress the current scopes into a single vars hash to add to the new scope scope.to_hash(true, true).each_pair { |k, v| local[k] = v } newscope.push_ephemerals([local]) end # Execute "futures" serially when running in BoltSpec result = yield newscope @id += 1 future = Bolt::PlanFuture.new(nil, @id, name: name, plan_id: plan_id) future.value = result @plan_futures << future future end |
#download_file(targets, source, destination, options = {}, _position = []) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 105 def download_file(targets, source, destination, = {}, _position = []) result = nil if (doub = @download_doubles[source] || @download_doubles[:default]) result = doub.process(targets, source, destination, ) end unless result targets = targets.map(&:name) @error_message = "Unexpected call to 'download_file(#{source}, #{destination}, #{targets}, #{})'" raise UnexpectedInvocation, @error_message end result end |
#finish_plan(_plan_result) ⇒ Object
332 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 332 def finish_plan(_plan_result); end |
#get_current_future(fiber) ⇒ Object
319 320 321 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 319 def get_current_future(fiber) @plan_futures.select { |f| f.fiber == fiber }&.first end |
#get_current_plan_id(fiber) ⇒ Object
323 324 325 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 323 def get_current_plan_id(fiber) get_current_future(fiber)&.current_plan end |
#get_futures_for_plan(plan_id:) ⇒ Object
305 306 307 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 305 def get_futures_for_plan(plan_id:) @plan_futures.select { |future| future.plan_id == plan_id } end |
#handle_event(_event) ⇒ Object
334 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 334 def handle_event(_event); end |
#in_parallel? ⇒ Boolean
280 281 282 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 280 def in_parallel? false end |
#log_action(*_args) ⇒ Object
217 218 219 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 217 def log_action(*_args) yield end |
#log_plan(_plan_name) ⇒ Object
221 222 223 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 221 def log_plan(_plan_name) yield end |
#module_file_id(file) ⇒ Object
45 46 47 48 49 50 51 52 53 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 45 def module_file_id(file) modpath = @modulepath.select { |path| file =~ /^#{path}/ } return nil unless modpath.size == 1 path = Pathname.new(file) relative = path.relative_path_from(Pathname.new(modpath.first)) segments = relative.to_path.split('/') ([segments[0]] + segments[2..-1]).join('/') end |
#plan_complete? ⇒ Boolean
Since Futures are executed immediately once created, this will always be true by the time it’s called.
315 316 317 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 315 def plan_complete? true end |
#prompt(_prompt, _options) ⇒ Object
336 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 336 def prompt(_prompt, ); end |
#publish_event(event) ⇒ Object
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 229 def publish_event(event) case event[:type] when :message unless @stub_out_message @error_message = "Unexpected call to 'out::message(#{event[:message]})'" raise UnexpectedInvocation, @error_message end @stub_out_message.process(event[:message]) when :verbose unless @stub_out_verbose @error_message = "Unexpected call to 'out::verbose(#{event[:message]})'" raise UnexpectedInvocation, @error_message end @stub_out_verbose.process(event[:message]) end end |
#queue_execute(targets) ⇒ Object
252 253 254 255 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 252 def queue_execute(targets) raise "Unexpected call to apply(#{targets})" unless @allow_apply targets end |
#report_apply(_statements, _resources) ⇒ Object
344 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 344 def report_apply(_statements, _resources); end |
#report_bundled_content(_mode, _name) ⇒ Object
340 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 340 def report_bundled_content(_mode, _name); end |
#report_file_source(_plan_function, _source) ⇒ Object
342 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 342 def report_file_source(_plan_function, _source); end |
#report_function_call(_function) ⇒ Object
338 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 338 def report_function_call(_function); end |
#report_noop_mode(_mode) ⇒ Object
348 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 348 def report_noop_mode(_mode); end |
#report_yaml_plan(_plan) ⇒ Object
346 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 346 def report_yaml_plan(_plan); end |
#round_robin ⇒ Object
358 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 358 def round_robin; end |
#run_command(targets, command, options = {}, _position = []) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 55 def run_command(targets, command, = {}, _position = []) result = nil if (doub = @command_doubles[command] || @command_doubles[:default]) result = doub.process(targets, command, ) end unless result targets = targets.map(&:name) @error_message = "Unexpected call to 'run_command(#{command}, #{targets}, #{})'" raise UnexpectedInvocation, @error_message end result end |
#run_in_thread ⇒ Object
Parallel function mocking
276 277 278 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 276 def run_in_thread yield end |
#run_plan(scope, plan_clj, params) ⇒ Object
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 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 139 def run_plan(scope, plan_clj, params) result = nil plan_name = plan_clj.closure_name # get the mock object either by plan name, or the default in case allow_any_plan # was called, if both are nil / don't exist, then dub will be nil and we'll fall # through to another conditional statement doub = @plan_doubles[plan_name] || @plan_doubles[:default] # rubocop:disable Lint/DuplicateBranch # High level: # - If we've explicitly allowed execution of the plan (normally the main plan # passed into BoltSpec::Plan::run_plan()), then execute it # - If we've explicitly "allowed/expected" the plan (mocked), # then run it through the mock object # - If we're allowing "any" plan to be executed, # then execute it # - Otherwise we have an error if @allowed_exec_plans.key?(plan_name) && @allowed_exec_plans[plan_name] == params # This plan's name + parameters were explicitly allowed to be executed. # run it with the real executor. # We require this functionality so that the BoltSpec::Plans.run_plan() # function can kick off the initial plan. In reality, no other plans should # be in this hash. result = @executor_real.run_plan(scope, plan_clj, params) elsif doub result = doub.process(scope, plan_clj, params) # the throw here is how Puppet exits out of a closure and returns a result # it throws this special symbol with a result object that is captured by # the run_plan Puppet function throw :return, result elsif @execute_any_plan # if the plan wasn't allowed or mocked out, and we're allowing any plan to be # executed, then execute the plan result = @executor_real.run_plan(scope, plan_clj, params) else # convert to JSON and back so that we get the ruby representation with all keys and # values converted to a string .to_s instead of their ruby object notation params_str = JSON.parse(params.to_json) @error_message = "Unexpected call to 'run_plan(#{plan_name}, #{params_str})'" raise UnexpectedInvocation, @error_message end # rubocop:enable Lint/DuplicateBranch result end |
#run_script(targets, script_path, arguments, options = {}, _position = []) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 68 def run_script(targets, script_path, arguments, = {}, _position = []) script = module_file_id(script_path) || script_path result = nil if (doub = @script_doubles[script] || @script_doubles[:default]) result = doub.process(targets, script, arguments, ) end unless result targets = targets.map(&:name) params = .merge('arguments' => arguments) @error_message = "Unexpected call to 'run_script(#{script}, #{targets}, #{params})'" raise UnexpectedInvocation, @error_message end result end |
#run_task(targets, task, arguments, options = {}, _position = []) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 83 def run_task(targets, task, arguments, = {}, _position = []) result = nil if (doub = @task_doubles[task.name] || @task_doubles[:default]) result = doub.process(targets, task.name, arguments, ) end unless result targets = targets.map(&:name) params = arguments.merge() @error_message = "Unexpected call to 'run_task(#{task.name}, #{targets}, #{params})'" raise UnexpectedInvocation, @error_message end result end |
#run_task_with(target_mapping, task, options = {}, _position = []) ⇒ Object
97 98 99 100 101 102 103 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 97 def run_task_with(target_mapping, task, = {}, _position = []) resultsets = target_mapping.map do |target, arguments| run_task([target], task, arguments, ) end.compact Bolt::ResultSet.new(resultsets.map(&:results).flatten) end |
#shutdown ⇒ Object
350 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 350 def shutdown; end |
#start_plan(_plan_context) ⇒ Object
352 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 352 def start_plan(_plan_context); end |
#stub_apply ⇒ Object
209 210 211 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 209 def stub_apply @allow_apply = true end |
#stub_out_message ⇒ Object
201 202 203 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 201 def @stub_out_message ||= ActionDouble.new(:PublishStub) end |
#stub_out_verbose ⇒ Object
205 206 207 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 205 def stub_out_verbose @stub_out_verbose ||= ActionDouble.new(:PublishStub) end |
#subscribe(_subscriber, _types = nil) ⇒ Object
354 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 354 def subscribe(_subscriber, _types = nil); end |
#transport(_protocol) ⇒ Object
Mocked for apply_prep
264 265 266 267 268 269 270 271 272 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 264 def transport(_protocol) Class.new do attr_reader :provided_features def initialize(features) @provided_features = features end end.new(transport_features) end |
#unsubscribe(_subscriber, _types = nil) ⇒ Object
356 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 356 def unsubscribe(_subscriber, _types = nil); end |
#upload_file(targets, source_path, destination, options = {}, _position = []) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 118 def upload_file(targets, source_path, destination, = {}, _position = []) source = module_file_id(source_path) || source_path result = nil if (doub = @upload_doubles[source] || @upload_doubles[:default]) result = doub.process(targets, source, destination, ) end unless result targets = targets.map(&:name) @error_message = "Unexpected call to 'upload_file(#{source}, #{destination}, #{targets}, #{})'" raise UnexpectedInvocation, @error_message end result end |
#wait(futures, **_kwargs) ⇒ Object
309 310 311 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 309 def wait(futures, **_kwargs) futures.map(&:value) end |
#wait_until_available(targets, _options) ⇒ Object
213 214 215 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 213 def wait_until_available(targets, ) Bolt::ResultSet.new(targets.map { |target| Bolt::Result.new(target) }) end |
#with_node_logging(_description, targets) ⇒ Object
Mocked for Apply so it does not compile and execute.
248 249 250 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 248 def with_node_logging(_description, targets) raise "Unexpected call to apply(#{targets})" unless @allow_apply end |
#with_plan_allowed_exec(plan_name, params) ⇒ Object
132 133 134 135 136 137 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 132 def with_plan_allowed_exec(plan_name, params) @allowed_exec_plans[plan_name] = params result = yield @allowed_exec_plans.delete(plan_name) result end |
#without_default_logging ⇒ Object
225 226 227 |
# File 'lib/bolt_spec/plans/mock_executor.rb', line 225 def without_default_logging yield end |