Module: Kitchen::Plugin

Defined in:
lib/kitchen/plugin.rb

Class Method Summary collapse

Class Method Details

.load(type, plugin, config) ⇒ Kitchen::<Module>::Base

Returns an instance of a plugin given a type, name, and config.

Parameters:

  • type (Module)

    a Kitchen::<Module> of one of the plugin types (Driver, Provisioner, Transport, Verifier)

  • plugin (String)

    a plugin name, which will be constantized

  • config (Hash)

    a configuration hash to initialize the plugin

Returns:

  • (Kitchen::<Module>::Base)

    a plugin instance

Raises:

  • (ClientError)

    if a plugin instance could not be created

  • (UserError)

    if the plugin's dependencies could not be met


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/kitchen/plugin.rb', line 33

def self.load(type, plugin, config)
  type_name = Kitchen::Util.snake_case(type.name.split("::").last)
  first_load = require("kitchen/#{type_name}/#{plugin}")

  str_const = Kitchen::Util.camel_case(plugin)
  klass = type.const_get(str_const)
  object = klass.new(config)
  object.verify_dependencies if first_load
  object
rescue UserError
  raise
rescue NameError => e
  raise ClientError, "Could not load the '#{plugin}' #{type_name}. Error: #{e.message}"
rescue LoadError => e
  available_plugins = plugins_available(type_name)
  error_message = if available_plugins.include?(plugin)
                    e.message
                  else
                    " Did you mean: #{available_plugins.join(", ")} ?" \
                    " Please ensure that your #{type_name} is installed as a gem or included" \
                    " in your Gemfile if using Bundler."
                  end
  raise ClientError, "Could not load the '#{plugin}' #{type_name} from the load path." + error_message
end

.plugins_available(plugin_type) ⇒ Array<String>

given a type of plugin, searches the Ruby load path for plugins of that type based on the path+naming convention that plugin loading is based upon

Parameters:

  • plugin_type (String)

    the name of a plugin type (e.g. driver, provisioner, transport, verifier)

Returns:

  • (Array<String>)

    a collection of Ruby filenames that are probably plugins of the given type


65
66
67
68
69
70
71
72
73
74
# File 'lib/kitchen/plugin.rb', line 65

def self.plugins_available(plugin_type)
  $LOAD_PATH.map { |load_path| Dir[File.expand_path("kitchen/#{plugin_type}/*.rb", load_path)] }
    .reject(&:empty?)
    .flatten
    .uniq
    .select { |plugin_path| File.readlines(plugin_path).grep(/^\s*class \w* </).any? }
    .map { |plugin_path| File.basename(plugin_path).gsub(/\.rb$/, "") }
    .reject { |plugin_name| plugin_name == "base" }
    .sort
end