class Ohai::Loader

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

Attributes

logger[R]

Public Class Methods

new(controller) click to toggle source
# File lib/ohai/loader.rb, line 33
def initialize(controller)
  @controller = controller
  @logger = controller.logger.with_child(subsystem: "loader")
  @v7_plugin_classes = []
end

Public Instance Methods

load_additional(from) click to toggle source

load additional plugins classes from a given directory @param from [String] path to a directory with additional plugins to load

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

loads all plugin classes

@return [Array<String>]

# File lib/ohai/loader.rb, line 60
def load_all
  plugin_files_by_dir.each do |plugin_file|
    load_plugin_class(plugin_file)
  end

  collect_v7_plugins
end
load_plugin(plugin_path) click to toggle source

Load a specified file as an ohai plugin and creates an instance of it. Not used by ohai itself, but is used in the specs to load plugins for testing

@private @param plugin_path [String]

# File lib/ohai/loader.rb, line 84
def load_plugin(plugin_path)
  plugin_class = load_plugin_class(plugin_path)
  return nil unless plugin_class.kind_of?(Class)
  if 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) click to toggle source

load an ohai plugin object class from file @param plugin_path String the path to the ohai plugin

@return [Object] class object for the ohai plugin defined in the file

# File lib/ohai/loader.rb, line 98
def load_plugin_class(plugin_path)
  # Read the contents of the plugin to understand if it's a V6 or V7 plugin.
  contents = ""
  begin
    logger.trace("Loading plugin at #{plugin_path}")
    contents << IO.read(plugin_path)
  rescue IOError, Errno::ENOENT
    logger.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
    raise Exceptions::IllegalPluginDefinition, "[DEPRECATION] Plugin at #{plugin_path}"\
    " is a version 6 plugin. Version 6 plugins are no longer supported by Ohai. This"\
    " plugin will need to be updated to the v7 Ohai plugin format. See"\
    " https://docs.chef.io/ohai_custom.html for v7 syntax."
  end
end
plugin_files_by_dir(plugin_dir = Ohai.config[:plugin_path]) click to toggle source

Searches all plugin paths and returns an Array of file paths to plugins

@param dir [Array, String] directory/directories to load plugins from @return [Array<String>]

# File lib/ohai/loader.rb, line 43
def plugin_files_by_dir(plugin_dir = Ohai.config[:plugin_path])
  Array(plugin_dir).map do |path|
    if Dir.exist?(path)
      Ohai::Log.trace("Searching for Ohai plugins in #{path}")

      escaped = ChefConfig::PathHelper.escape_glob_dir(path)
      Dir[File.join(escaped, "**", "*.rb")]
    else
      Ohai::Log.debug("The plugin path #{path} does not exist. Skipping...")
      []
    end
  end.flatten
end

Private Instance Methods

collect_provides(plugin) click to toggle source
# File lib/ohai/loader.rb, line 122
def collect_provides(plugin)
  plugin_provides = plugin.class.provides_attrs
  @controller.provides_map.set_providers_for(plugin, plugin_provides)
end
collect_v7_plugins() click to toggle source
# File lib/ohai/loader.rb, line 127
def collect_v7_plugins
  @v7_plugin_classes.each do |plugin_class|
    load_v7_plugin(plugin_class)
  end
end
load_v7_plugin(plugin_class) click to toggle source
# File lib/ohai/loader.rb, line 169
def load_v7_plugin(plugin_class)
  plugin = plugin_class.new(@controller.data, @controller.logger)
  collect_provides(plugin)
  plugin
end
load_v7_plugin_class(contents, plugin_path) click to toggle source

load an Ohai v7 plugin class from a string of the object @param contents [String] text of the plugin object @param plugin_path [String] the path to the plugin file where the contents came from

@return [Ohai::DSL::Plugin::VersionVII] Ohai plugin object

# File lib/ohai/loader.rb, line 138
def load_v7_plugin_class(contents, plugin_path)
  plugin_class = eval(contents, TOPLEVEL_BINDING, plugin_path) # rubocop: disable Security/Eval
  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 # rubocop: disable Lint/ShadowedException
  raise
rescue Ohai::Exceptions::InvalidPluginName => e
  logger.warn("Plugin Name Error: <#{plugin_path}>: #{e.message}")
rescue Ohai::Exceptions::IllegalPluginDefinition => e
  logger.warn("Plugin Definition Error: <#{plugin_path}>: #{e.message}")
rescue NoMethodError => e
  logger.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
    logger.warn("Plugin Syntax Error: <#{plugin_path}>: #{part}")
  end
rescue Exception, Errno::ENOENT => e
  logger.warn("Plugin Error: <#{plugin_path}>: #{e.message}")
  logger.trace("Plugin Error: <#{plugin_path}>: #{e.inspect}, #{e.backtrace.join('\n')}")
end