This adjusts how triggers are implemented during a normal run. Any defined triggers which are applicable are located and injected into the run stack as the stack is built, including hook type triggers. Support is included for dynamic hook lookup. The data type used when defining triggers has also been relaxed to support symbols, strings, or constants.
290 lines
8.4 KiB
Ruby
290 lines
8.4 KiB
Ruby
require "log4r"
|
|
|
|
module Vagrant
|
|
module Plugin
|
|
module V2
|
|
# This class maintains a list of all the registered plugins as well
|
|
# as provides methods that allow querying all registered components of
|
|
# those plugins as a single unit.
|
|
class Manager
|
|
attr_reader :registered
|
|
|
|
def initialize
|
|
@logger = Log4r::Logger.new("vagrant::plugin::v2::manager")
|
|
@registered = []
|
|
end
|
|
|
|
# This returns all the action hooks.
|
|
#
|
|
# @return [Array]
|
|
def action_hooks(hook_name)
|
|
result = []
|
|
|
|
@registered.each do |plugin|
|
|
result += plugin.components.action_hooks[Plugin::ALL_ACTIONS]
|
|
result += plugin.components.action_hooks[hook_name]
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
# Find all hooks that are applicable for the given key. This
|
|
# lookup does not include hooks which are defined for ALL_ACTIONS.
|
|
# Key lookups will match on either string or symbol values. The
|
|
# provided keys is broken down into multiple parts for lookups,
|
|
# which allows defining hooks with an entire namespaced name,
|
|
# or a short suffx. For example:
|
|
#
|
|
# Assume we are given an action class
|
|
# key = Vagrant::Action::Builtin::SyncedFolders
|
|
#
|
|
# The list of keys that will be checked for hooks:
|
|
# ["Vagrant::Action::Builtin::SyncedFolders", "vagrant_action_builtin_synced_folders",
|
|
# "Action::Builtin::SyncedFolders", "action_builtin_synced_folders",
|
|
# "Builtin::SyncedFolders", "builtin_synced_folders",
|
|
# "SyncedFolders", "synced_folders"]
|
|
#
|
|
# @param key [Class, String] key Key for hook lookups
|
|
# @return [Array<Proc>]
|
|
def find_action_hooks(key)
|
|
result = []
|
|
|
|
generate_hook_keys(key).each do |k|
|
|
@registered.each do |plugin|
|
|
result += plugin.components.action_hooks[k]
|
|
result += plugin.components.action_hooks[k.to_sym]
|
|
end
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
# Generate all valid lookup keys for given key
|
|
#
|
|
# @param [Class, String] key Base key for generation
|
|
# @return [Array<String>] all valid keys
|
|
def generate_hook_keys(key)
|
|
if key.is_a?(Class)
|
|
key = key.name.to_s
|
|
else
|
|
key = key.to_s
|
|
end
|
|
parts = key.split("::")
|
|
[].tap do |keys|
|
|
until parts.empty?
|
|
x = parts.join("::")
|
|
keys << x
|
|
y = x.gsub(/([a-z])([A-Z])/, '\1_\2').gsub('::', '_').downcase
|
|
keys << y if x != y
|
|
parts.shift
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered commands.
|
|
#
|
|
# @return [Registry<Symbol, Array<Proc, Hash>>]
|
|
def commands
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.commands)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered communicators.
|
|
#
|
|
# @return [Hash]
|
|
def communicators
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.communicator)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered configuration classes.
|
|
#
|
|
# @return [Hash]
|
|
def config
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.configs[:top])
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered guests.
|
|
#
|
|
# @return [Hash]
|
|
def guests
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.guests)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered guest capabilities.
|
|
#
|
|
# @return [Hash]
|
|
def guest_capabilities
|
|
results = Hash.new { |h, k| h[k] = Registry.new }
|
|
|
|
@registered.each do |plugin|
|
|
plugin.components.guest_capabilities.each do |guest, caps|
|
|
results[guest].merge!(caps)
|
|
end
|
|
end
|
|
|
|
results
|
|
end
|
|
|
|
# This returns all the registered guests.
|
|
#
|
|
# @return [Hash]
|
|
def hosts
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.hosts)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered host capabilities.
|
|
#
|
|
# @return [Hash]
|
|
def host_capabilities
|
|
results = Hash.new { |h, k| h[k] = Registry.new }
|
|
|
|
@registered.each do |plugin|
|
|
plugin.components.host_capabilities.each do |host, caps|
|
|
results[host].merge!(caps)
|
|
end
|
|
end
|
|
|
|
results
|
|
end
|
|
|
|
# This returns all registered providers.
|
|
#
|
|
# @return [Hash]
|
|
def providers
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.providers)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the registered provider capabilities.
|
|
#
|
|
# @return [Hash]
|
|
def provider_capabilities
|
|
results = Hash.new { |h, k| h[k] = Registry.new }
|
|
|
|
@registered.each do |plugin|
|
|
plugin.components.provider_capabilities.each do |provider, caps|
|
|
results[provider].merge!(caps)
|
|
end
|
|
end
|
|
|
|
results
|
|
end
|
|
|
|
# This returns all the config classes for the various providers.
|
|
#
|
|
# @return [Hash]
|
|
def provider_configs
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.configs[:provider])
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the config classes for the various provisioners.
|
|
#
|
|
# @return [Registry]
|
|
def provisioner_configs
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.configs[:provisioner])
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all registered provisioners.
|
|
#
|
|
# @return [Hash]
|
|
def provisioners
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.provisioner)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all registered pushes.
|
|
#
|
|
# @return [Registry]
|
|
def pushes
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.pushes)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all the config classes for the various pushes.
|
|
#
|
|
# @return [Registry]
|
|
def push_configs
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.configs[:push])
|
|
end
|
|
end
|
|
end
|
|
|
|
# This returns all synced folder implementations.
|
|
#
|
|
# @return [Registry]
|
|
def synced_folders
|
|
Registry.new.tap do |result|
|
|
@registered.each do |plugin|
|
|
result.merge!(plugin.components.synced_folders)
|
|
end
|
|
end
|
|
end
|
|
|
|
# This registers a plugin. This should _NEVER_ be called by the public
|
|
# and should only be called from within Vagrant. Vagrant will
|
|
# automatically register V2 plugins when a name is set on the
|
|
# plugin.
|
|
def register(plugin)
|
|
if !@registered.include?(plugin)
|
|
@logger.info("Registered plugin: #{plugin.name}")
|
|
@registered << plugin
|
|
end
|
|
end
|
|
|
|
# This clears out all the registered plugins. This is only used by
|
|
# unit tests and should not be called directly.
|
|
def reset!
|
|
@registered.clear
|
|
end
|
|
|
|
# This unregisters a plugin so that its components will no longer
|
|
# be used. Note that this should only be used for testing purposes.
|
|
def unregister(plugin)
|
|
if @registered.include?(plugin)
|
|
@logger.info("Unregistered: #{plugin.name}")
|
|
@registered.delete(plugin)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|