class AutomateIt::Plugin::Manager
Plugin::Manager
¶ ↑
A manager provides high-level wrappers for features, e.g. installing software packages. It does not actually implement these features, but instead manages a set of drivers. When one of the manager’s wrapper methods is called, it queries the drivers to find the most suitable one and dispatches the user’s request to that driver.
For example, the PlatformManager
is a Manager
class that manages a set of Driver
instances, including PlatformManager::Uname
and PlatformManager::LSB
. When you invoke the high-level PlatformManager#query
wrapper method, it interrogates the drivers to find which one is best-suited for this method and then dispatches the request to that driver’s low-level implementation of this method.
The manager subclasses typically have no functionality of their own and just contain wrapper methods and documentation.
Attributes
Drivers for this manager as a hash of driver tokens to driver instances.
Public Class Methods
Declare that this manager class is abstract. It can be subclassed but will not be instantiated by the Interpreter
.
# File lib/automateit/plugin/manager.rb, line 32 def self.abstract_manager classes.delete(self) end
Methods to alias into the Interpreter
, specified as an array of symbols.
# File lib/automateit/plugin/manager.rb, line 40 def self.alias_methods(*methods) self.aliased_methods ||= Set.new self.aliased_methods.merge(methods.flatten) end
Public Instance Methods
Returns the Driver
with the specified token. E.g., :apt
will return the APT
driver.
# File lib/automateit/plugin/manager.rb, line 90 def [](token) return @drivers[token] end
Is a driver available for this method
and args
? Uses automatic-detection routines and returns a boolean to indicate if a suitable driver is available. Unlike driver_for
, this will not raise an exception.
# File lib/automateit/plugin/manager.rb, line 214 def available?(method, *args, &block) begin driver_for(method, *args, &block) true rescue NotImplementedError false end end
Manipulate the default driver. Without arguments, gets the driver token as a symbol. With argument, sets the default driver to the token
, e.g., the argument :apt
will make the APT
driver the default.
# File lib/automateit/plugin/manager.rb, line 97 def default(token=nil) if token.nil? @default else @default = token end end
Set the default driver to the token
. See also default
.
# File lib/automateit/plugin/manager.rb, line 106 def default=(token) default(token) end
Dispatch a method by guessing its name. This is the recommended way to write wrappers for a Manager
methods.
Example:
class MyManager < Plugin::Manager # Your RDoc here def my_method(*args) # Will guess that you want to +dispatch_to+ the +my_method+ by # introspecting the name of the wrapper method. dispatch(*args) end ... end
# File lib/automateit/plugin/manager.rb, line 123 def dispatch(*args, &block) # Extract caller's method as symbol to save user from having to specify it method = caller[0].match(/:in `(.+?)'/)[1].to_sym dispatch_to(method, *args, &block) end
Same as dispatch
but returns nil if couldn’t dispatch, rather than raising an exception.
# File lib/automateit/plugin/manager.rb, line 171 def dispatch_safely(*args, &block) method = caller[0].match(/:in `(.+?)'/)[1].to_sym dispatch_safely_to(method, *args, &block) end
Same as dispatch_to
but returns nil if couldn’t dispatch, rather than raising an exception.
# File lib/automateit/plugin/manager.rb, line 161 def dispatch_safely_to(method, *args, &block) begin dispatch_to(method, *args, &block) rescue NotImplementedError nil end end
Dispatch the method
with args
and block
to the appropriate driver. If the arguments include an option of the form :with => :mytoken
argument, then the method will be dispatched to the driver represented by :mytoken
. If no :with argument is specified, the most-suitable driver will be automatically selected. If no suitable driver is available, a NotImplementedError will be raised.
Examples:
# Run 'hostnames' method on most appropriate AddressManager driver: address_manager.dispatch_to(:hostnames) # Run AddressManager::Portable#hostnames address_manager.dispatch_to(:hostnames, :with => :portable)
You will typically not want to use this method directly and instead write wrappers that call dispatch
because it can guess the name of the method
argument for you.
# File lib/automateit/plugin/manager.rb, line 146 def dispatch_to(method, *args, &block) list, options = args_and_opts(*args) driver = \ if options and options[:with] @drivers[options[:with].to_sym] elsif default @drivers[default.to_sym] else driver_for(method, *args, &block) end driver.send(method, *args, &block) end
Get the most suitable driver for this method
and args
. Uses automatic-detection routines and returns the most suitable driver instance found, else raises a NotImplementedError if no suitable driver is found.
# File lib/automateit/plugin/manager.rb, line 201 def driver_for(method, *args, &block) driver, level = driver_suitability_levels_for(method, *args, &block).sort_by{|k,v| v}.last if driver and level > 0 return @drivers[driver] else raise NotImplementedError.new("can't find driver for method '#{method}' with arguments: #{args.inspect}") end end
Returns structure which helps choose a suitable driver for the method
and args
. Result is a hash of driver tokens and their suitability levels.
For example, if we ask the AddressManager
for suitability levels for the AddressManager#hostnames
method, we might find that there are two drivers (:portable is the token for AddressManager::Portable
) and that the :linux driver is most appropriate because it has the highest suitability level:
address_manager.driver_suitability_levels_for(:hostnames) # => {:portable=>1, :linux=>2}
# File lib/automateit/plugin/manager.rb, line 188 def driver_suitability_levels_for(method, *args, &block) results = {} @drivers.each_pair do |name, driver| next unless driver.respond_to?(method) results[name] = driver.suitability(method, *args, &block) end return results end
Instantiate drivers for this manager. This method is smart enough that it can be called multiple times and will only instantiate drivers it hasn’t instantiated yet. All drivers will share an instance of the Interpreter
, thus providing common state storage.
# File lib/automateit/plugin/manager.rb, line 73 def instantiate_drivers @drivers ||= {} self.class.driver_classes.each do |driver_class| driver_token = driver_class.token unless @drivers[driver_token] @drivers[driver_token] = driver_class.allocate end end self.class.driver_classes.each do |driver_class| driver_token = driver_class.token @drivers[driver_token].setup( :interpreter => @interpreter, :manager => self) end end
Options:
-
:default – The token of the driver to set as the default.
AutomateIt::Common#setup
# File lib/automateit/plugin/manager.rb, line 56 def setup(opts={}) super(opts) @default ||= nil instantiate_drivers if driver = opts[:default] || opts[:driver] default(opts[:default]) if opts[:default] @drivers[driver].setup(opts) end end