Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove V6 plugin Struct to reduce memory consumption #1333

Merged
merged 1 commit into from
Dec 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 32 additions & 47 deletions lib/ohai/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,59 +24,42 @@

module Ohai

# Ohai plugin loader. Finds all the plugins in your
# `Ohai.config[:plugin_path]` (supports a single or multiple path setting
# 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.
class Loader

# 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.
PluginFile = Struct.new(:path, :plugin_root) do

# Finds all the *.rb files under the configured paths in :plugin_path
def self.find_all_in(plugin_dir)
unless Dir.exist?(plugin_dir)
Ohai::Log.info("The plugin path #{plugin_dir} does not exist. Skipping...")
return []
end

Ohai::Log.trace("Searching for Ohai plugins in #{plugin_dir}")

escaped = ChefConfig::PathHelper.escape_glob_dir(plugin_dir)
Dir[File.join(escaped, "**", "*.rb")].map do |file|
new(file, plugin_dir)
end
end
end

attr_reader :logger

def initialize(controller)
@controller = controller
@logger = controller.logger.with_child(subsystem: "loader")
@v7_plugin_classes = []
end

# Searches all plugin paths and returns an Array of PluginFile objects
# representing each plugin file.
# 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<Ohai::Loader::PluginFile>]
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
# @return [Array<String>]
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

# loads all plugin classes
#
# @return [Array<String>]
def load_all
plugin_files_by_dir.each do |plugin_file|
load_plugin_class(plugin_file.path, plugin_file.plugin_root)
load_plugin_class(plugin_file)
end

collect_v7_plugins
Expand All @@ -88,19 +71,18 @@ 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.path, plugin_file.plugin_root)
plugin = load_plugin_class(plugin_file)
load_v7_plugin(plugin)
end
end

# 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.
# Not used by ohai itself, but is used in the specs to load plugins for testing
#
# @private
# @param plugin_path [String]
# @param plugin_dir_path [String]
def load_plugin(plugin_path, plugin_dir_path = nil)
plugin_class = load_plugin_class(plugin_path, plugin_dir_path)
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)
Expand All @@ -109,13 +91,11 @@ def load_plugin(plugin_path, plugin_dir_path = nil)
end
end

# Reads the file specified by `plugin_path` and returns a class object for
# the ohai plugin defined therein.
# load an ohai plugin object class from file
# @param plugin_path String the path to the ohai plugin
#
# 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`
def load_plugin_class(plugin_path, plugin_dir_path = nil)
# @return [Object] class object for the ohai plugin defined in the file
def load_plugin_class(plugin_path)
# Read the contents of the plugin to understand if it's a V6 or V7 plugin.
contents = ""
begin
Expand Down Expand Up @@ -150,6 +130,11 @@ def collect_v7_plugins
end
end

# 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
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
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/loader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@

describe "when plugin directory does not exist" do
it "logs an invalid plugin path warning" do
expect(Ohai::Log).to receive(:info).with(/The plugin path.*does not exist/)
expect(Ohai::Log).to receive(:debug).with(/The plugin path.*does not exist/)
allow(Dir).to receive(:exist?).with("/bogus/dir").and_return(false)
Ohai::Loader::PluginFile.find_all_in("/bogus/dir")
loader.plugin_files_by_dir("/bogus/dir")
end
end
end
Expand Down