Class: Bolt::Plugin
- Inherits:
-
Object
- Object
- Bolt::Plugin
- Defined in:
- lib/bolt/plugin.rb,
lib/bolt/plugin/task.rb,
lib/bolt/plugin/pkcs7.rb,
lib/bolt/plugin/module.rb,
lib/bolt/plugin/prompt.rb,
lib/bolt/plugin/puppetdb.rb,
lib/bolt/plugin/install_agent.rb
Defined Under Namespace
Classes: InstallAgent, Module, Pkcs7, PluginContext, PluginError, Prompt, Puppetdb, Task
Constant Summary collapse
- KNOWN_HOOKS =
%i[ puppet_library resolve_reference secret_encrypt secret_decrypt secret_createkeys validate_resolve_reference ].freeze
- RUBY_PLUGINS =
%w[install_agent task pkcs7 prompt].freeze
- BUILTIN_PLUGINS =
%w[task terraform pkcs7 prompt vault aws_inventory puppetdb azure_inventory yaml].freeze
- DEFAULT_PLUGIN_HOOKS =
{ 'puppet_library' => { 'plugin' => 'puppet_agent', 'stop_service' => true } }.freeze
Instance Attribute Summary collapse
-
#pal ⇒ Object
readonly
Returns the value of attribute pal.
-
#plugin_context ⇒ Object
readonly
Returns the value of attribute plugin_context.
-
#plugin_hooks ⇒ Object
Returns the value of attribute plugin_hooks.
Class Method Summary collapse
Instance Method Summary collapse
- #add_module_plugin(plugin_name) ⇒ Object
-
#add_plugin(plugin) ⇒ Object
Generally this is private.
- #add_ruby_plugin(plugin_name) ⇒ Object
-
#by_name(plugin_name) ⇒ Object
Calling by_name or get_hook will load any module based plugin automatically.
- #config_for_plugin(plugin_name) ⇒ Object
- #get_hook(plugin_name, hook) ⇒ Object
-
#initialize(config, pal, analytics) ⇒ Plugin
constructor
A new instance of Plugin.
- #modules ⇒ Object
-
#reference?(input) ⇒ Boolean
Checks whether a given value is a _plugin reference.
-
#resolve_references(data) ⇒ Object
Evaluate all _plugin references in a data structure.
-
#resolve_top_level_references(data) ⇒ Object
Iteratively resolves “top-level” references until the result no longer has top-level references.
Constructor Details
#initialize(config, pal, analytics) ⇒ Plugin
Returns a new instance of Plugin.
154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/bolt/plugin.rb', line 154 def initialize(config, pal, analytics) @config = config @analytics = analytics @plugin_context = PluginContext.new(config, pal, self) @plugins = {} @pal = pal @unknown = Set.new @resolution_stack = [] @unresolved_plugin_configs = config.plugins.dup @plugin_hooks = DEFAULT_PLUGIN_HOOKS.dup end |
Instance Attribute Details
#pal ⇒ Object (readonly)
Returns the value of attribute pal.
149 150 151 |
# File 'lib/bolt/plugin.rb', line 149 def pal @pal end |
#plugin_context ⇒ Object (readonly)
Returns the value of attribute plugin_context.
149 150 151 |
# File 'lib/bolt/plugin.rb', line 149 def plugin_context @plugin_context end |
#plugin_hooks ⇒ Object
Returns the value of attribute plugin_hooks.
150 151 152 |
# File 'lib/bolt/plugin.rb', line 150 def plugin_hooks @plugin_hooks end |
Class Method Details
.setup(config, pal, pdb_client, analytics) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/bolt/plugin.rb', line 122 def self.setup(config, pal, pdb_client, analytics) plugins = new(config, pal, analytics) # PDB is special because it needs the PDB client. Since it has no config, # we can just add it first. plugins.add_plugin(Bolt::Plugin::Puppetdb.new(pdb_client)) # Initialize any plugins referenced in config. This will also indirectly # initialize any plugins they depend on. if plugins.reference?(config.plugins) msg = "The 'plugins' setting cannot be set by a plugin reference" raise PluginError.new(msg, 'bolt/plugin-error') end config.plugins.keys.each do |plugin| plugins.by_name(plugin) end plugins.plugin_hooks.merge!(plugins.resolve_references(config.plugin_hooks)) plugins end |
Instance Method Details
#add_module_plugin(plugin_name) ⇒ Object
189 190 191 192 193 194 195 196 197 |
# File 'lib/bolt/plugin.rb', line 189 def add_module_plugin(plugin_name) opts = { context: @plugin_context, config: config_for_plugin(plugin_name) } plugin = Bolt::Plugin::Module.load(plugin_name, modules, opts) add_plugin(plugin) end |
#add_plugin(plugin) ⇒ Object
Generally this is private. Puppetdb is special though
171 172 173 |
# File 'lib/bolt/plugin.rb', line 171 def add_plugin(plugin) @plugins[plugin.name] = plugin end |
#add_ruby_plugin(plugin_name) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/bolt/plugin.rb', line 175 def add_ruby_plugin(plugin_name) cls_name = Bolt::Util.snake_name_to_class_name(plugin_name) filename = "bolt/plugin/#{plugin_name}" require filename cls = Kernel.const_get("Bolt::Plugin::#{cls_name}") opts = { context: @plugin_context, config: config_for_plugin(plugin_name) } plugin = cls.new(**opts) add_plugin(plugin) end |
#by_name(plugin_name) ⇒ Object
Calling by_name or get_hook will load any module based plugin automatically
223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/bolt/plugin.rb', line 223 def by_name(plugin_name) return @plugins[plugin_name] if @plugins.include?(plugin_name) begin if RUBY_PLUGINS.include?(plugin_name) add_ruby_plugin(plugin_name) elsif !@unknown.include?(plugin_name) add_module_plugin(plugin_name) end rescue PluginError::Unknown @unknown << plugin_name nil end end |
#config_for_plugin(plugin_name) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/bolt/plugin.rb', line 199 def config_for_plugin(plugin_name) return {} unless @unresolved_plugin_configs.include?(plugin_name) if @resolution_stack.include?(plugin_name) msg = "Configuration for plugin '#{plugin_name}' depends on the plugin itself" raise PluginError.new(msg, 'bolt/plugin-error') else @resolution_stack.push(plugin_name) config = resolve_references(@unresolved_plugin_configs[plugin_name]) @unresolved_plugin_configs.delete(plugin_name) @resolution_stack.pop config end end |
#get_hook(plugin_name, hook) ⇒ Object
213 214 215 216 217 218 219 220 |
# File 'lib/bolt/plugin.rb', line 213 def get_hook(plugin_name, hook) plugin = by_name(plugin_name) raise PluginError::Unknown, plugin_name unless plugin raise PluginError::UnsupportedHook.new(plugin_name, hook) unless plugin.hooks.include?(hook) @analytics.report_bundled_content("Plugin #{hook}", plugin_name) plugin.method(hook) end |
#modules ⇒ Object
166 167 168 |
# File 'lib/bolt/plugin.rb', line 166 def modules @modules ||= Bolt::Module.discover(@pal.modulepath) end |
#reference?(input) ⇒ Boolean
Checks whether a given value is a _plugin reference
302 303 304 |
# File 'lib/bolt/plugin.rb', line 302 def reference?(input) input.is_a?(Hash) && input.key?('_plugin') end |
#resolve_references(data) ⇒ Object
Evaluate all _plugin references in a data structure. Leaves are evaluated and then their parents are evaluated with references replaced by their values. If the result of a reference contains more references, they are resolved again before continuing to ascend the tree. The final result will not contain any references.
242 243 244 245 246 247 248 249 |
# File 'lib/bolt/plugin.rb', line 242 def resolve_references(data) Bolt::Util.postwalk_vals(data) do |value| reference?(value) ? resolve_references(resolve_single_reference(value)) : value end rescue SystemStackError raise Bolt::Error.new("Stack depth exceeded while recursively resolving references.", "bolt/recursive-reference-loop") end |
#resolve_top_level_references(data) ⇒ Object
Iteratively resolves “top-level” references until the result no longer has top-level references. A top-level reference is one which is not contained within another hash. It may be either the actual top-level result or arbitrarily nested within arrays. If parameters of the reference are themselves references, they will be looked. Any remaining references nested inside the result will not be evaluated once the top-level result is not a reference. This is used to resolve the ‘targets` and `groups` keys which are allowed to be references or arrays of references, but which may return data with nested references that should be resolved lazily. The end result will either be a single hash or a flat array of hashes.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/bolt/plugin.rb', line 262 def resolve_top_level_references(data) if data.is_a?(Array) data.flat_map { |elem| resolve_top_level_references(elem) } elsif reference?(data) partially_resolved = data.map do |k, v| [k, resolve_references(v)] end.to_h fully_resolved = resolve_single_reference(partially_resolved) # The top-level reference may have returned more references, so repeat the process resolve_top_level_references(fully_resolved) else data end end |