mirror of
https://github.com/inspec/inspec
synced 2024-11-27 15:10:44 +00:00
94 lines
2.8 KiB
Ruby
94 lines
2.8 KiB
Ruby
|
# encoding: utf-8
|
||
|
# author: Dominik Richter
|
||
|
# author: Christoph Hartmann
|
||
|
|
||
|
class PluginRegistry
|
||
|
attr_reader :registry
|
||
|
|
||
|
def initialize
|
||
|
@registry = {}
|
||
|
end
|
||
|
|
||
|
# Resolve a target via available plugins.
|
||
|
#
|
||
|
# @param [String] target to resolve
|
||
|
# @return [Plugin] plugin instance if it can be resolved, nil otherwise
|
||
|
def resolve(target)
|
||
|
modules.each do |m|
|
||
|
res = m.resolve(target)
|
||
|
return res unless res.nil?
|
||
|
end
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
# Get all registered plugins sorted by priority, with highest first
|
||
|
#
|
||
|
# @return [Array[Plugin]] sorted list of plugins
|
||
|
def modules
|
||
|
@registry.values
|
||
|
.sort_by { |x| x.respond_to?(:priority) ? x.priority : 0 }
|
||
|
.reverse
|
||
|
end
|
||
|
end
|
||
|
|
||
|
class PluginRegistry
|
||
|
class Plugin
|
||
|
# Retrieve the plugin registry associated with this plugin
|
||
|
#
|
||
|
# @return [PluginRegistry] plugin registry for this plugin
|
||
|
def self.plugin_registry
|
||
|
fail "Plugin #{self} does not implement `self.plugin_registry()`. This method is required"
|
||
|
end
|
||
|
|
||
|
# Register a new plugin by name
|
||
|
#
|
||
|
# @param [String] the unique name of this plugin
|
||
|
# @return [nil] disregard
|
||
|
def self.name(name)
|
||
|
fail "Trying to register #{self} with name == nil" if name.nil?
|
||
|
@name = name
|
||
|
plugin_registry.registry[name] = self
|
||
|
end
|
||
|
|
||
|
# This plugin's priority. Set it by providing the priority as an
|
||
|
# argument. Higher numbers ensure that the plugin is
|
||
|
# called early to check if a target belongs to it. When called without
|
||
|
# an argument, it retrieves this plugin's priority. Defaults to 0.
|
||
|
#
|
||
|
# @param [Numeric] Priority as a number. Will only be set if != nil
|
||
|
# @return [Numeric] This plugin's priority
|
||
|
def self.priority(x = nil)
|
||
|
@priority = x unless x.nil?
|
||
|
@priority || 0
|
||
|
end
|
||
|
|
||
|
# Try to resolve the target. If this plugin cannot handle it, the result
|
||
|
# will be nil. If, however, the plugin can resolve it, the resulting
|
||
|
# object will be an instance of this plugin. This means, that the interface
|
||
|
# that this base class provides, is the basis for the returned type.
|
||
|
#
|
||
|
# @param [String] target to try to resolve
|
||
|
# @return [Plugin] instance if it can be resolved, nil otherwise
|
||
|
def self.resolve(_target)
|
||
|
fail "Plugin #{self} does not implement `self.resolve(target)`. This method is required"
|
||
|
end
|
||
|
|
||
|
# When a plugin's resolve doesn't lead to the final state, it can
|
||
|
# use this method to hand it back for another resolver to handle.
|
||
|
#
|
||
|
# @param [Any] the current target that needs resolving
|
||
|
# @param [Plugin] an instance of the calling resolver
|
||
|
# @return [Plugin] instance if it can be resolved, nil otherwise
|
||
|
def self.resolve_next(target, parent)
|
||
|
res = plugin_registry.resolve(target)
|
||
|
res.parent = parent
|
||
|
res
|
||
|
end
|
||
|
|
||
|
attr_reader :target
|
||
|
attr_accessor :parent
|
||
|
end
|
||
|
end
|