Module: Kitchen::Plugin

Defined in:
lib/kitchen/plugin.rb,
lib/kitchen/plugin_base.rb
more...

Defined Under Namespace

Classes: Base

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

[View source]

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

[View source]

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