class Ohai::Loader

Ohai plugin loader. Finds all the plugins in your `Ohai.config` (supports a single or multiple path setting here), evaluates them and returns plugin objects.

Constants

PluginFile

Simple struct like objects to track the path of a plugin and the root directory of plugins in which we found it. We don't care about the relative paths of v7 plugins, but in v6 plugins, dependencies are specified by calling `require_plugin` with a relative path. To manage this, we track the path and root of each file as we discover them so we can feed this into the v6 “dependency solver” as we load them.

V6PluginClass

Simple struct to track a v6 plugin's class, file path, and the root of the plugin dir from which it was loaded.

Public Class Methods

new(controller) click to toggle source
# File lib/ohai/loader.rb, line 65
def initialize(controller)
  @controller = controller
  @v6_plugin_classes = []
  @v7_plugin_classes = []
end

Public Instance Methods

load_additional(from) click to toggle source
# File lib/ohai/loader.rb, line 88
def load_additional(from)
  from = [ Ohai.config[:plugin_path], from].flatten
  plugin_files_by_dir(from).collect do |plugin_file|
    Ohai::Log.debug "Loading additional plugin: #{plugin_file}"
    plugin = load_plugin_class(plugin_file.path, plugin_file.plugin_root)
    load_v7_plugin(plugin)
  end
end
load_all() click to toggle source
# File lib/ohai/loader.rb, line 79
def load_all
  plugin_files_by_dir.each do |plugin_file|
    load_plugin_class(plugin_file.path, plugin_file.plugin_root)
  end

  collect_v6_plugins
  collect_v7_plugins
end
load_plugin(plugin_path, plugin_dir_path = nil) click to toggle source

Load a specified file as an ohai plugin and creates an instance of it. Not used by ohai itself, but can be used to load a plugin for testing purposes. plugin_dir_path is required when loading a v6 plugin.

# File lib/ohai/loader.rb, line 101
def load_plugin(plugin_path, plugin_dir_path = nil)
  plugin_class = load_plugin_class(plugin_path, plugin_dir_path)
  return nil unless plugin_class.kind_of?(Class)
  case
  when plugin_class < Ohai::DSL::Plugin::VersionVI
    load_v6_plugin(plugin_class, plugin_path, plugin_dir_path)
  when plugin_class < Ohai::DSL::Plugin::VersionVII
    load_v7_plugin(plugin_class)
  else
    raise Exceptions::IllegalPluginDefinition, "cannot create plugin of type #{plugin_class}"
  end
end
load_plugin_class(plugin_path, plugin_dir_path = nil) click to toggle source

Reads the file specified by `plugin_path` and returns a class object for the ohai plugin defined therein.

If `plugin_dir_path` is given, and the file at `plugin_path` is a v6 plugin, the 'relative path' of the plugin (used by `require_plugin()`) is computed by finding the relative path from `plugin_dir_path` to `plugin_path`

# File lib/ohai/loader.rb, line 120
    def load_plugin_class(plugin_path, plugin_dir_path = nil)
      # Read the contents of the plugin to understand if it's a V6 or V7 plugin.
      contents = ""
      begin
        Ohai::Log.debug("Loading plugin at #{plugin_path}")
        contents << IO.read(plugin_path)
      rescue IOError, Errno::ENOENT
        Ohai::Log.warn("Unable to open or read plugin at #{plugin_path}")
        return nil
      end

      # We assume that a plugin is a V7 plugin if it contains Ohai.plugin in its contents.
      if contents.include?("Ohai.plugin")
        load_v7_plugin_class(contents, plugin_path)
      else
        Ohai::Log.warn("[DEPRECATION] Plugin at #{plugin_path} is a version 6 plugin. \
Version 6 plugins will not be supported in Chef/Ohai 14. \
Please upgrade your plugin to version 7 plugin format. \
For more information visit here: docs.chef.io/ohai_custom.html")

        load_v6_plugin_class(contents, plugin_path, plugin_dir_path)
      end
    end
plugin_files_by_dir(dir = Ohai.config[:plugin_path]) click to toggle source

Searches all plugin paths and returns an Array of PluginFile objects representing each plugin file.

# File lib/ohai/loader.rb, line 73
def plugin_files_by_dir(dir = Ohai.config[:plugin_path])
  Array(dir).inject([]) do |plugin_files, plugin_path|
    plugin_files + PluginFile.find_all_in(plugin_path)
  end
end

Private Instance Methods

collect_provides(plugin) click to toggle source
# File lib/ohai/loader.rb, line 146
def collect_provides(plugin)
  plugin_provides = plugin.class.provides_attrs
  @controller.provides_map.set_providers_for(plugin, plugin_provides)
end
collect_v6_plugins() click to toggle source
# File lib/ohai/loader.rb, line 155
def collect_v6_plugins
  @v6_plugin_classes.each do |plugin_spec|
    plugin = load_v6_plugin(plugin_spec.plugin_class, plugin_spec.plugin_path, plugin_spec.plugin_dir_path)
    loaded_v6_plugin(plugin, plugin_spec.plugin_path, plugin_spec.plugin_dir_path)
  end
end
collect_v7_plugins() click to toggle source
# File lib/ohai/loader.rb, line 162
def collect_v7_plugins
  @v7_plugin_classes.each do |plugin_class|
    load_v7_plugin(plugin_class)
  end
end
load_v6_plugin(plugin_class, plugin_path, plugin_dir_path) click to toggle source
# File lib/ohai/loader.rb, line 174
def load_v6_plugin(plugin_class, plugin_path, plugin_dir_path)
  plugin_class.new(@controller, plugin_path, plugin_dir_path)
end
load_v6_plugin_class(contents, plugin_path, plugin_dir_path) click to toggle source
# File lib/ohai/loader.rb, line 168
def load_v6_plugin_class(contents, plugin_path, plugin_dir_path)
  plugin_class = Class.new(Ohai::DSL::Plugin::VersionVI) { collect_contents(contents) }
  @v6_plugin_classes << V6PluginClass.new(plugin_class, plugin_path, plugin_dir_path)
  plugin_class
end
load_v7_plugin(plugin_class) click to toggle source
# File lib/ohai/loader.rb, line 222
def load_v7_plugin(plugin_class)
  plugin = plugin_class.new(@controller.data)
  collect_provides(plugin)
  plugin
end
load_v7_plugin_class(contents, plugin_path) click to toggle source
# File lib/ohai/loader.rb, line 191
def load_v7_plugin_class(contents, plugin_path)
  plugin_class = eval(contents, TOPLEVEL_BINDING, plugin_path)
  unless plugin_class.kind_of?(Class) && plugin_class < Ohai::DSL::Plugin
    raise Ohai::Exceptions::IllegalPluginDefinition, "Plugin file cannot contain any statements after the plugin definition"
  end
  plugin_class.sources << plugin_path
  @v7_plugin_classes << plugin_class unless @v7_plugin_classes.include?(plugin_class)
  plugin_class
rescue SystemExit, Interrupt
  raise
rescue Ohai::Exceptions::InvalidPluginName => e
  Ohai::Log.warn("Plugin Name Error: <#{plugin_path}>: #{e.message}")
rescue Ohai::Exceptions::IllegalPluginDefinition => e
  Ohai::Log.warn("Plugin Definition Error: <#{plugin_path}>: #{e.message}")
rescue NoMethodError => e
  Ohai::Log.warn("Plugin Method Error: <#{plugin_path}>: unsupported operation \'#{e.name}\'")
rescue SyntaxError => e
  # split on occurrences of
  #    <env>: syntax error,
  #    <env>:##: syntax error,
  # to remove from error message
  parts = e.message.split(/<.*>[:[0-9]+]*: syntax error, /)
  parts.each do |part|
    next if part.length == 0
    Ohai::Log.warn("Plugin Syntax Error: <#{plugin_path}>: #{part}")
  end
rescue Exception, Errno::ENOENT => e
  Ohai::Log.warn("Plugin Error: <#{plugin_path}>: #{e.message}")
  Ohai::Log.debug("Plugin Error: <#{plugin_path}>: #{e.inspect}, #{e.backtrace.join('\n')}")
end
loaded_v6_plugin(plugin, plugin_file_path, plugin_dir_path) click to toggle source

Capture the plugin in @v6_dependency_solver if it is a V6 plugin to be able to resolve V6 dependencies later on. We are using the partial path in the dep solver as a key.

# File lib/ohai/loader.rb, line 181
def loaded_v6_plugin(plugin, plugin_file_path, plugin_dir_path)
  partial_path = Pathname.new(plugin_file_path).relative_path_from(Pathname.new(plugin_dir_path)).to_s

  unless v6_dependency_solver.has_key?(partial_path)
    v6_dependency_solver[partial_path] = plugin
  else
    Ohai::Log.debug("Plugin '#{plugin_file_path}' is already loaded.")
  end
end
v6_dependency_solver() click to toggle source
# File lib/ohai/loader.rb, line 151
def v6_dependency_solver
  @controller.v6_dependency_solver
end