Merge pull request #3720 from inspec/cw/plugins-move-activate-method

Plugins: Relocate plugin activate() method to Activator class, add simpler search method
This commit is contained in:
Clinton Wolfe 2019-02-06 13:23:45 -05:00 committed by GitHub
commit 14ef38f365
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 23 deletions

View file

@ -40,7 +40,8 @@ module Inspec
if hook if hook
# OK, load the hook if it hasn't been already. We'll then know a module, # OK, load the hook if it hasn't been already. We'll then know a module,
# which we can then inject into the context # which we can then inject into the context
registry.activate(:control_dsl, method_name) unless hook.activated? hook.activate
# Inject the module's methods into the context. # Inject the module's methods into the context.
# implementation_class is the field name, but this is actually a module. # implementation_class is the field name, but this is actually a module.
self.class.include(hook.implementation_class) self.class.include(hook.implementation_class)

View file

@ -38,7 +38,7 @@ module Inspec::DSL
if hook if hook
# OK, load the hook if it hasn't been already. We'll then know a module, # OK, load the hook if it hasn't been already. We'll then know a module,
# which we can then inject into the context # which we can then inject into the context
registry.activate(:outer_profile_dsl, method_name) unless hook.activated? hook.activate
# Inject the module's methods into the context # Inject the module's methods into the context
# implementation_class is the field name, but this is actually a module. # implementation_class is the field name, but this is actually a module.
self.class.include(hook.implementation_class) self.class.include(hook.implementation_class)

View file

@ -52,7 +52,7 @@ module Inspec
if hook if hook
# OK, load the hook if it hasn't been already. We'll then know a module, # OK, load the hook if it hasn't been already. We'll then know a module,
# which we can then inject into the resource # which we can then inject into the resource
registry.activate(:resource_dsl, method_name) unless hook.activated? hook.activate
# Inject the module's methods into the resource as class methods. # Inject the module's methods into the resource as class methods.
# implementation_class is the field name, but this is actually a module. # implementation_class is the field name, but this is actually a module.
extend(hook.implementation_class) extend(hook.implementation_class)

View file

@ -3,7 +3,7 @@ module Inspec::Plugin::V2
:plugin_name, :plugin_name,
:plugin_type, :plugin_type,
:activator_name, :activator_name,
:'activated?', :activated?,
:exception, :exception,
:activation_proc, :activation_proc,
:implementation_class, :implementation_class,
@ -14,8 +14,29 @@ module Inspec::Plugin::V2
end end
def activated?(new_value = nil) def activated?(new_value = nil)
return self[:'activated?'] if new_value.nil? return self[:activated?] if new_value.nil?
self[:'activated?'] = new_value self[:activated?] = new_value
end
# Load a plugin, but if an error is encountered, store it and continue
def activate
return if activated?
# rubocop: disable Lint/RescueException
begin
impl_class = self[:activation_proc].call
self[:activated?] = true
self[:implementation_class] = impl_class
rescue Exception => ex
self[:exception] = ex
Inspec::Log.error "Could not activate #{self[:plugin_type]} hook named '#{self[:activator_name]}' for plugin #{self[:plugin_name]}"
end
# rubocop: enable Lint/RescueException
end
# Load a plugin, but if an error is encountered, re-throw it
def activate!
activate
raise exception if exception
end end
end end
end end

View file

@ -102,7 +102,7 @@ module Inspec::Plugin::V2
# OK, activate. # OK, activate.
if activate_me if activate_me
registry.activate(:cli_command, act.activator_name) act.activate
act.implementation_class.register_with_thor act.implementation_class.register_with_thor
end end
end end

View file

@ -67,19 +67,15 @@ module Inspec::Plugin::V2
end end
end end
def activate(plugin_type, hook_name) # Convenience method for when you expect exactly one
activator = find_activators(plugin_type: plugin_type, activator_name: hook_name).first def find_activator(filters = {})
# We want to capture literally any possible exception here, since we are storing them. matched_plugins = find_activators(filters)
# rubocop: disable Lint/RescueException if matched_plugins.count > 1
begin raise Inspec::Plugin::V2::LoadError, "Plugin hooks search returned multiple results for filter #{filters.inspect} - use more filters, or use find_activators (plural)"
impl_class = activator.activation_proc.call elsif matched_plugins.empty?
activator.activated?(true) raise Inspec::Plugin::V2::LoadError, "Plugin hooks search returned zero results for filter #{filters.inspect}"
activator.implementation_class = impl_class
rescue Exception => ex
activator.exception = ex
Inspec::Log.error "Could not activate #{activator.plugin_type} hook named '#{activator.activator_name}' for plugin #{plugin_name}"
end end
# rubocop: enable Lint/RescueException matched_plugins.first
end end
def register(name, status) def register(name, status)

View file

@ -17,7 +17,7 @@ module Inspec
if hook if hook
# OK, load the hook if it hasn't been already. We'll then know a module, # OK, load the hook if it hasn't been already. We'll then know a module,
# which we can then inject into the context # which we can then inject into the context
registry.activate(:describe_dsl, method_name) unless hook.activated? hook.activate
# Inject the module's methods into the example group contexts. # Inject the module's methods into the example group contexts.
# implementation_class is the field name, but this is actually a module. # implementation_class is the field name, but this is actually a module.
@ -46,7 +46,7 @@ module Inspec
if hook if hook
# OK, load the hook if it hasn't been already. We'll then know a module, # OK, load the hook if it hasn't been already. We'll then know a module,
# which we can then inject into the context # which we can then inject into the context
registry.activate(:test_dsl, method_name) unless hook.activated? hook.activate
# Inject the module's methods into the example group contexts. # Inject the module's methods into the example group contexts.
# implementation_class is the field name, but this is actually a module. # implementation_class is the field name, but this is actually a module.

View file

@ -187,7 +187,6 @@ class PluginLoaderTests < MiniTest::Test
# Management methods for activation # Management methods for activation
assert_respond_to status, :activators, 'A plugin status should respond to `activators`' assert_respond_to status, :activators, 'A plugin status should respond to `activators`'
assert_respond_to registry, :find_activators, 'Registry should respond to `find_activators`' assert_respond_to registry, :find_activators, 'Registry should respond to `find_activators`'
assert_respond_to registry, :activate, 'Registry should respond to `activate`'
# Finding an Activator # Finding an Activator
assert_kind_of Array, status.activators, 'status should have an array for activators' assert_kind_of Array, status.activators, 'status should have an array for activators'
@ -205,7 +204,7 @@ class PluginLoaderTests < MiniTest::Test
assert_nil activator.implementation_class, 'Test activator should not know implementation class prior to activation' assert_nil activator.implementation_class, 'Test activator should not know implementation class prior to activation'
refute InspecPlugins::MeaningOfLife.const_defined?(:MockPlugin), 'impl_class should not be defined prior to activation' refute InspecPlugins::MeaningOfLife.const_defined?(:MockPlugin), 'impl_class should not be defined prior to activation'
registry.activate(:mock_plugin_type, :'meaning-of-life-the-universe-and-everything') activator.activate
# Activation postconditions # Activation postconditions
assert activator.activated?, 'Test activator should be activated after activate' assert activator.activated?, 'Test activator should be activated after activate'