307 lines
8.9 KiB
Ruby
307 lines
8.9 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
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 returns all the registered synced folder capabilities.
|
|
#
|
|
# @return [Hash]
|
|
def synced_folder_capabilities
|
|
results = Hash.new { |h, k| h[k] = Registry.new }
|
|
|
|
@registered.each do |plugin|
|
|
plugin.components.synced_folder_capabilities.each do |synced_folder, caps|
|
|
results[synced_folder].merge!(caps)
|
|
end
|
|
end
|
|
|
|
results
|
|
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
|