module MCollective::PluginManager - mcollective version 2.12.5

# module MCollective::PluginManager

A simple plugin manager, it stores one plugin each of a specific type the idea is that we can only have one security provider, one connector etc.

### Public Class Methods

<<(plugin) click to toggle source

Adds a plugin to the list of plugins, we expect a hash like:

    {:type => "base",
     :class => foo.new}

or like:

    {:type => "base",
     :class => "Foo::Bar"}

In the event that we already have a class with the given type an exception will be raised.

If the :class passed is a `String` then we will delay instantiation till the first time someone asks for the plugin, this is because most likely the registration gets done by inherited() hooks, at which point the plugin class is not final.

If we were to do a .new here the Class initialize method would get called and not the plugins, we there for only initialize the classes when they get requested via []

By default all plugin instances are cached and returned later so there's always a single instance. You can pass :single_instance => false when calling this to instruct it to always return a new instance when a copy is requested. This only works with sending a `String` for :class.

       # File lib/mcollective/pluginmanager.rb
    30 def self.<<(plugin)
    31   plugin[:single_instance] = true unless plugin.include?(:single_instance)
    32
    33   type = plugin[:type]
    34   klass = plugin[:class]
    35   single = plugin[:single_instance]
    36
    37   raise("Plugin #{type} already loaded") if @plugins.include?(type)
    38
    39
    40   # If we get a string then store 'nil' as the instance, signalling that we'll
    41   # create the class later on demand.
    42   if klass.is_a?(String)
    43     @plugins[type] = {:loadtime => Time.now, :class => klass, :instance => nil, :single => single}
    44     Log.debug("Registering plugin #{type} with class #{klass} single_instance: #{single}")
    45   else
    46     @plugins[type] = {:loadtime => Time.now, :class => klass.class, :instance => klass, :single => true}
    47     Log.debug("Registering plugin #{type} with class #{klass.class} single_instance: true")
    48   end
    49 end

[](plugin) click to toggle source

Gets a plugin by type

       # File lib/mcollective/pluginmanager.rb
    72 def self.[](plugin)
    73   raise("No plugin #{plugin} defined") unless @plugins.include?(plugin)
    74
    75   klass = @plugins[plugin][:class]
    76
    77   if @plugins[plugin][:single]
    78     # Create an instance of the class if one hasn't been done before
    79     if @plugins[plugin][:instance] == nil
    80       Log.debug("Returning new plugin #{plugin} with class #{klass}")
    81       @plugins[plugin][:instance] = create_instance(klass)
    82     else
    83       Log.debug("Returning cached plugin #{plugin} with class #{klass}")
    84     end
    85
    86     @plugins[plugin][:instance]
    87   else
    88     Log.debug("Returning new plugin #{plugin} with class #{klass}")
    89     create_instance(klass)
    90   end
    91 end

clear() click to toggle source

deletes all registered plugins

       # File lib/mcollective/pluginmanager.rb
    67 def self.clear
    68   @plugins.clear
    69 end

create_instance(klass) click to toggle source

use eval to create an instance of a class

        # File lib/mcollective/pluginmanager.rb
     94 def self.create_instance(klass)
     95   begin
     96     eval("#{klass}.new")
     97   rescue Exception => e
     98     raise("Could not create instance of plugin #{klass}: #{e}")
     99   end
    100 end

delete(plugin) click to toggle source

Removes a plugim the list

       # File lib/mcollective/pluginmanager.rb
    52 def self.delete(plugin)
    53   @plugins.delete(plugin) if @plugins.include?(plugin)
    54 end

find(type, extension="rb") click to toggle source

Finds plugins in all configured libdirs

    find("agent")

will return an array of just agent names, for example:

    ["puppetd", "package"]

Can also be used to find files of other extensions:

    find("agent", "ddl")

Will return the same list but only of files with extension .ddl in the agent subdirectory

        # File lib/mcollective/pluginmanager.rb
    116 def self.find(type, extension="rb")
    117   extension = ".#{extension}" unless extension.match(/^\./)
    118
    119   plugins = []
    120
    121   Config.instance.libdir.each do |libdir|
    122     plugdir = File.join([libdir, "mcollective", type.to_s])
    123     next unless File.directory?(plugdir)
    124
    125     Dir.new(plugdir).grep(/#{extension}$/).map do |plugin|
    126       plugins << File.basename(plugin, extension)
    127     end
    128   end
    129
    130   plugins.sort.uniq
    131 end

find_and_load(type, extension="rb") { |plugin| ... } click to toggle source

Finds and loads from disk all plugins from all libdirs that match certain criteria.

    find_and_load("pluginpackager")

Will find all .rb files in the libdir/mcollective/pluginpackager/ directory in all libdirs and load them from disk.

You can influence what plugins get loaded using a block notation:

    find_and_load("pluginpackager") do |plugin|
       plugin.match(/puppet/)
    end

This will load only plugins matching /puppet/

        # File lib/mcollective/pluginmanager.rb
    148 def self.find_and_load(type, extension="rb")
    149   extension = ".#{extension}" unless extension.match(/^\./)
    150
    151   klasses = find(type, extension).map do |plugin|
    152     if block_given?
    153       next unless yield(plugin)
    154     end
    155
    156     "%s::%s::%s" % [ "MCollective", type.capitalize, plugin.capitalize ]
    157   end.compact
    158
    159   klasses.sort.uniq.each {|klass| loadclass(klass, true)}
    160 end

grep(regex) click to toggle source

Grep's over the plugin list and returns the list found

        # File lib/mcollective/pluginmanager.rb
    176 def self.grep(regex)
    177   @plugins.keys.grep(regex)
    178 end

include?(plugin) click to toggle source

Finds out if we have a plugin with the given name

       # File lib/mcollective/pluginmanager.rb
    57 def self.include?(plugin)
    58   @plugins.include?(plugin)
    59 end

loadclass(klass, squash_failures=false) click to toggle source

Loads a class from file by doing some simple search/replace on class names and then doing a require.

        # File lib/mcollective/pluginmanager.rb
    164 def self.loadclass(klass, squash_failures=false)
    165   fname = klass.gsub("::", "/").downcase + ".rb"
    166
    167   Log.debug("Loading #{klass} from #{fname}")
    168
    169   load fname
    170 rescue Exception => e
    171   Log.error("Failed to load #{klass}: #{e}")
    172   raise unless squash_failures
    173 end

pluginlist() click to toggle source

Provides a list of plugins we know about

       # File lib/mcollective/pluginmanager.rb
    62 def self.pluginlist
    63   @plugins.keys.sort
    64 end