openbolt 5.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Puppetfile +52 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +60 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +51 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +71 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +55 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +65 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +93 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +33 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +38 -0
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +208 -0
- data/bolt-modules/boltlib/lib/puppet/functions/background.rb +62 -0
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +57 -0
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +130 -0
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +31 -0
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +52 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +87 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +34 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +35 -0
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +74 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +97 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +47 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +52 -0
- data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +40 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +42 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resource.rb +53 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +106 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +291 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +145 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +164 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +211 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +48 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +43 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +145 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +38 -0
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +101 -0
- data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +29 -0
- data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +131 -0
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +59 -0
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +39 -0
- data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +50 -0
- data/bolt-modules/boltlib/types/planresult.pp +18 -0
- data/bolt-modules/boltlib/types/targetspec.pp +7 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +42 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +20 -0
- data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
- data/bolt-modules/file/lib/puppet/functions/file/delete.rb +21 -0
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +28 -0
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +20 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +33 -0
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +28 -0
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +24 -0
- data/bolt-modules/log/lib/puppet/functions/log/debug.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/error.rb +40 -0
- data/bolt-modules/log/lib/puppet/functions/log/fatal.rb +40 -0
- data/bolt-modules/log/lib/puppet/functions/log/info.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/trace.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/warn.rb +41 -0
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +36 -0
- data/bolt-modules/out/lib/puppet/functions/out/verbose.rb +35 -0
- data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +65 -0
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +20 -0
- data/exe/bolt +17 -0
- data/guides/debugging.yaml +27 -0
- data/guides/inventory.yaml +23 -0
- data/guides/links.yaml +12 -0
- data/guides/logging.yaml +17 -0
- data/guides/module.yaml +18 -0
- data/guides/modulepath.yaml +24 -0
- data/guides/project.yaml +21 -0
- data/guides/targets.yaml +28 -0
- data/guides/transports.yaml +22 -0
- data/lib/bolt/analytics.rb +233 -0
- data/lib/bolt/application.rb +806 -0
- data/lib/bolt/applicator.rb +368 -0
- data/lib/bolt/apply_inventory.rb +93 -0
- data/lib/bolt/apply_result.rb +154 -0
- data/lib/bolt/apply_target.rb +90 -0
- data/lib/bolt/bolt_option_parser.rb +1226 -0
- data/lib/bolt/catalog/logging.rb +15 -0
- data/lib/bolt/catalog.rb +144 -0
- data/lib/bolt/cli.rb +949 -0
- data/lib/bolt/config/modulepath.rb +30 -0
- data/lib/bolt/config/options.rb +673 -0
- data/lib/bolt/config/transport/base.rb +133 -0
- data/lib/bolt/config/transport/docker.rb +34 -0
- data/lib/bolt/config/transport/jail.rb +33 -0
- data/lib/bolt/config/transport/local.rb +39 -0
- data/lib/bolt/config/transport/lxd.rb +34 -0
- data/lib/bolt/config/transport/options.rb +431 -0
- data/lib/bolt/config/transport/orch.rb +41 -0
- data/lib/bolt/config/transport/podman.rb +33 -0
- data/lib/bolt/config/transport/remote.rb +24 -0
- data/lib/bolt/config/transport/ssh.rb +138 -0
- data/lib/bolt/config/transport/winrm.rb +63 -0
- data/lib/bolt/config.rb +515 -0
- data/lib/bolt/container_result.rb +105 -0
- data/lib/bolt/error.rb +194 -0
- data/lib/bolt/executor.rb +539 -0
- data/lib/bolt/fiber_executor.rb +190 -0
- data/lib/bolt/inventory/group.rb +446 -0
- data/lib/bolt/inventory/inventory.rb +391 -0
- data/lib/bolt/inventory/options.rb +139 -0
- data/lib/bolt/inventory/target.rb +293 -0
- data/lib/bolt/inventory.rb +120 -0
- data/lib/bolt/logger.rb +252 -0
- data/lib/bolt/module.rb +54 -0
- data/lib/bolt/module_installer/installer.rb +44 -0
- data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
- data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
- data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
- data/lib/bolt/module_installer/puppetfile.rb +131 -0
- data/lib/bolt/module_installer/resolver.rb +129 -0
- data/lib/bolt/module_installer/specs/forge_spec.rb +91 -0
- data/lib/bolt/module_installer/specs/git_spec.rb +150 -0
- data/lib/bolt/module_installer/specs/id/base.rb +116 -0
- data/lib/bolt/module_installer/specs/id/gitclone.rb +120 -0
- data/lib/bolt/module_installer/specs/id/github.rb +90 -0
- data/lib/bolt/module_installer/specs/id/gitlab.rb +92 -0
- data/lib/bolt/module_installer/specs.rb +95 -0
- data/lib/bolt/module_installer.rb +208 -0
- data/lib/bolt/node/errors.rb +55 -0
- data/lib/bolt/node/output.rb +29 -0
- data/lib/bolt/outputter/human.rb +958 -0
- data/lib/bolt/outputter/json.rb +205 -0
- data/lib/bolt/outputter/logger.rb +76 -0
- data/lib/bolt/outputter/rainbow.rb +118 -0
- data/lib/bolt/outputter.rb +57 -0
- data/lib/bolt/pal/issues.rb +19 -0
- data/lib/bolt/pal/logging.rb +17 -0
- data/lib/bolt/pal/yaml_plan/evaluator.rb +83 -0
- data/lib/bolt/pal/yaml_plan/loader.rb +94 -0
- data/lib/bolt/pal/yaml_plan/parameter.rb +63 -0
- data/lib/bolt/pal/yaml_plan/step/command.rb +45 -0
- data/lib/bolt/pal/yaml_plan/step/download.rb +37 -0
- data/lib/bolt/pal/yaml_plan/step/eval.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/message.rb +31 -0
- data/lib/bolt/pal/yaml_plan/step/plan.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/resources.rb +170 -0
- data/lib/bolt/pal/yaml_plan/step/script.rb +62 -0
- data/lib/bolt/pal/yaml_plan/step/task.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/upload.rb +37 -0
- data/lib/bolt/pal/yaml_plan/step/verbose.rb +31 -0
- data/lib/bolt/pal/yaml_plan/step.rb +223 -0
- data/lib/bolt/pal/yaml_plan/transpiler.rb +90 -0
- data/lib/bolt/pal/yaml_plan.rb +172 -0
- data/lib/bolt/pal.rb +847 -0
- data/lib/bolt/plan_creator.rb +219 -0
- data/lib/bolt/plan_future.rb +86 -0
- data/lib/bolt/plan_result.rb +44 -0
- data/lib/bolt/plugin/cache.rb +76 -0
- data/lib/bolt/plugin/env_var.rb +54 -0
- data/lib/bolt/plugin/module.rb +276 -0
- data/lib/bolt/plugin/prompt.rb +36 -0
- data/lib/bolt/plugin/puppet_connect_data.rb +84 -0
- data/lib/bolt/plugin/puppetdb.rb +124 -0
- data/lib/bolt/plugin/task.rb +72 -0
- data/lib/bolt/plugin.rb +380 -0
- data/lib/bolt/project.rb +219 -0
- data/lib/bolt/project_manager/config_migrator.rb +113 -0
- data/lib/bolt/project_manager/inventory_migrator.rb +67 -0
- data/lib/bolt/project_manager/migrator.rb +39 -0
- data/lib/bolt/project_manager/module_migrator.rb +203 -0
- data/lib/bolt/project_manager.rb +221 -0
- data/lib/bolt/puppetdb/client.rb +153 -0
- data/lib/bolt/puppetdb/config.rb +176 -0
- data/lib/bolt/puppetdb/instance.rb +146 -0
- data/lib/bolt/puppetdb.rb +15 -0
- data/lib/bolt/r10k_log_proxy.rb +30 -0
- data/lib/bolt/rerun.rb +55 -0
- data/lib/bolt/resource_instance.rb +133 -0
- data/lib/bolt/result.rb +247 -0
- data/lib/bolt/result_set.rb +128 -0
- data/lib/bolt/shell/bash/tmpdir.rb +62 -0
- data/lib/bolt/shell/bash.rb +516 -0
- data/lib/bolt/shell/powershell/snippets.rb +181 -0
- data/lib/bolt/shell/powershell.rb +365 -0
- data/lib/bolt/shell.rb +105 -0
- data/lib/bolt/target.rb +174 -0
- data/lib/bolt/task/puppet_server.rb +27 -0
- data/lib/bolt/task/run.rb +55 -0
- data/lib/bolt/task.rb +163 -0
- data/lib/bolt/transport/base.rb +252 -0
- data/lib/bolt/transport/docker/connection.rb +150 -0
- data/lib/bolt/transport/docker.rb +23 -0
- data/lib/bolt/transport/jail/connection.rb +81 -0
- data/lib/bolt/transport/jail.rb +21 -0
- data/lib/bolt/transport/local/connection.rb +106 -0
- data/lib/bolt/transport/local.rb +20 -0
- data/lib/bolt/transport/lxd/connection.rb +115 -0
- data/lib/bolt/transport/lxd.rb +26 -0
- data/lib/bolt/transport/orch/connection.rb +111 -0
- data/lib/bolt/transport/orch.rb +271 -0
- data/lib/bolt/transport/podman/connection.rb +102 -0
- data/lib/bolt/transport/podman.rb +19 -0
- data/lib/bolt/transport/remote.rb +41 -0
- data/lib/bolt/transport/simple.rb +54 -0
- data/lib/bolt/transport/ssh/connection.rb +321 -0
- data/lib/bolt/transport/ssh/exec_connection.rb +140 -0
- data/lib/bolt/transport/ssh.rb +48 -0
- data/lib/bolt/transport/winrm/connection.rb +378 -0
- data/lib/bolt/transport/winrm.rb +33 -0
- data/lib/bolt/util/format.rb +68 -0
- data/lib/bolt/util/puppet_log_level.rb +21 -0
- data/lib/bolt/util.rb +465 -0
- data/lib/bolt/validator.rb +227 -0
- data/lib/bolt/version.rb +5 -0
- data/lib/bolt.rb +8 -0
- data/lib/bolt_server/acl.rb +39 -0
- data/lib/bolt_server/base_config.rb +112 -0
- data/lib/bolt_server/config.rb +64 -0
- data/lib/bolt_server/file_cache.rb +200 -0
- data/lib/bolt_server/request_error.rb +11 -0
- data/lib/bolt_server/schemas/action-check_node_connections.json +14 -0
- data/lib/bolt_server/schemas/action-run_command.json +12 -0
- data/lib/bolt_server/schemas/action-run_script.json +47 -0
- data/lib/bolt_server/schemas/action-run_task.json +20 -0
- data/lib/bolt_server/schemas/action-upload_file.json +47 -0
- data/lib/bolt_server/schemas/partials/target-any.json +10 -0
- data/lib/bolt_server/schemas/partials/target-ssh.json +88 -0
- data/lib/bolt_server/schemas/partials/target-winrm.json +67 -0
- data/lib/bolt_server/schemas/partials/task.json +94 -0
- data/lib/bolt_server/schemas/transport-ssh.json +25 -0
- data/lib/bolt_server/schemas/transport-winrm.json +19 -0
- data/lib/bolt_server/transport_app.rb +554 -0
- data/lib/bolt_spec/bolt_context.rb +226 -0
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +51 -0
- data/lib/bolt_spec/plans/action_stubs/download_stub.rb +66 -0
- data/lib/bolt_spec/plans/action_stubs/plan_stub.rb +55 -0
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +59 -0
- data/lib/bolt_spec/plans/action_stubs/task_stub.rb +57 -0
- data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +65 -0
- data/lib/bolt_spec/plans/action_stubs.rb +196 -0
- data/lib/bolt_spec/plans/mock_executor.rb +361 -0
- data/lib/bolt_spec/plans/publish_stub.rb +49 -0
- data/lib/bolt_spec/plans.rb +190 -0
- data/lib/bolt_spec/run.rb +246 -0
- data/lib/logging_extensions/logging.rb +13 -0
- data/libexec/apply_catalog.rb +130 -0
- data/libexec/bolt_catalog +68 -0
- data/libexec/custom_facts.rb +63 -0
- data/libexec/query_resources.rb +75 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/count.rb +21 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/nodes.rb +22 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/targets.rb +21 -0
- data/modules/aggregate/plans/count.pp +56 -0
- data/modules/aggregate/plans/targets.pp +56 -0
- data/modules/canary/lib/puppet/functions/canary/merge.rb +13 -0
- data/modules/canary/lib/puppet/functions/canary/random_split.rb +22 -0
- data/modules/canary/lib/puppet/functions/canary/skip.rb +25 -0
- data/modules/canary/plans/init.pp +100 -0
- data/modules/puppet_connect/plans/test_input_data.pp +94 -0
- data/modules/puppetdb_fact/plans/init.pp +20 -0
- data/resources/bolt_bash_completion.sh +214 -0
- metadata +735 -0
@@ -0,0 +1,806 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
require_relative '../bolt/plan_creator'
|
6
|
+
require_relative '../bolt/util'
|
7
|
+
|
8
|
+
module Bolt
|
9
|
+
class Application
|
10
|
+
attr_reader :analytics, :config, :executor, :inventory, :logger, :pal, :plugins
|
11
|
+
private :analytics, :config, :executor, :inventory, :logger, :pal, :plugins
|
12
|
+
|
13
|
+
def initialize(
|
14
|
+
analytics:,
|
15
|
+
config:,
|
16
|
+
executor:,
|
17
|
+
inventory:,
|
18
|
+
pal:,
|
19
|
+
plugins:
|
20
|
+
)
|
21
|
+
@analytics = analytics
|
22
|
+
@config = config
|
23
|
+
@executor = executor
|
24
|
+
@inventory = inventory
|
25
|
+
@logger = Bolt::Logger.logger(self)
|
26
|
+
@pal = pal
|
27
|
+
@plugins = plugins
|
28
|
+
end
|
29
|
+
|
30
|
+
# Shuts down the application.
|
31
|
+
#
|
32
|
+
def shutdown
|
33
|
+
executor.shutdown
|
34
|
+
end
|
35
|
+
|
36
|
+
# Apply Puppet manifest code to a list of targets.
|
37
|
+
#
|
38
|
+
# @param manifest [String, NilClass] The path to a Puppet manifest file.
|
39
|
+
# @param targets [Array[String]] The targets to run on.
|
40
|
+
# @param code [String] Puppet manifest code to apply.
|
41
|
+
# @param noop [Boolean] Whether to apply in no-operation mode.
|
42
|
+
# @return [Bolt::ResultSet]
|
43
|
+
#
|
44
|
+
def apply(manifest, targets, code: '', noop: false)
|
45
|
+
manifest_code = if manifest
|
46
|
+
Bolt::Util.validate_file('manifest', manifest)
|
47
|
+
File.read(File.expand_path(manifest))
|
48
|
+
else
|
49
|
+
code
|
50
|
+
end
|
51
|
+
|
52
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
53
|
+
|
54
|
+
Puppet[:tasks] = false
|
55
|
+
ast = pal.parse_manifest(manifest_code, manifest)
|
56
|
+
|
57
|
+
if defined?(ast.body) &&
|
58
|
+
(ast.body.is_a?(Puppet::Pops::Model::HostClassDefinition) ||
|
59
|
+
ast.body.is_a?(Puppet::Pops::Model::ResourceTypeDefinition))
|
60
|
+
message = "Manifest only contains definitions and will result in no changes on the targets. "\
|
61
|
+
"Definitions must be declared for their resources to be applied. You can read more "\
|
62
|
+
"about defining and declaring classes and types in the Puppet documentation at "\
|
63
|
+
"https://puppet.com/docs/puppet/latest/lang_classes.html and "\
|
64
|
+
"https://puppet.com/docs/puppet/latest/lang_defined_types.html"
|
65
|
+
Bolt::Logger.warn("empty_manifest", message)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Apply logging looks like plan logging
|
69
|
+
executor.publish_event(type: :plan_start, plan: nil)
|
70
|
+
|
71
|
+
with_benchmark do
|
72
|
+
apply_prep_results = pal.in_plan_compiler(executor, inventory, plugins.puppetdb_client) do |compiler|
|
73
|
+
compiler.call_function('apply_prep', targets, '_catch_errors' => true)
|
74
|
+
end
|
75
|
+
|
76
|
+
apply_results = pal.with_bolt_executor(executor, inventory, plugins.puppetdb_client) do
|
77
|
+
Puppet.lookup(:apply_executor)
|
78
|
+
.apply_ast(ast, apply_prep_results.ok_set.targets, catch_errors: true, noop: noop)
|
79
|
+
end
|
80
|
+
|
81
|
+
Bolt::ResultSet.new(apply_prep_results.error_set.results + apply_results.results)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Run a command on a list of targets.
|
86
|
+
#
|
87
|
+
# @param command [String] The command.
|
88
|
+
# @param targets [Array[String]] The targets to run on.
|
89
|
+
# @param env_vars [Hash] Environment variables to set on the target.
|
90
|
+
# @return [Bolt::ResultSet]
|
91
|
+
#
|
92
|
+
def run_command(command, targets, env_vars: nil)
|
93
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
94
|
+
|
95
|
+
with_benchmark do
|
96
|
+
executor.run_command(targets, command, env_vars: env_vars)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Download a file from a list of targets to a directory on the controller.
|
101
|
+
#
|
102
|
+
# @param source [String] The path to the file on the targets.
|
103
|
+
# @param destination [String] The path to the directory on the controller.
|
104
|
+
# @param targets [Array[String]] The targets to run on.
|
105
|
+
# @return [Bolt::ResultSet]
|
106
|
+
#
|
107
|
+
def download_file(source, destination, targets)
|
108
|
+
destination = File.expand_path(destination, Dir.pwd)
|
109
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
110
|
+
|
111
|
+
with_benchmark do
|
112
|
+
executor.download_file(targets, source, destination)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Upload a file from the controller to a list of targets.
|
117
|
+
#
|
118
|
+
# @param source [String] The path to the file on the controller.
|
119
|
+
# @param destination [String] The destination path on the targets.
|
120
|
+
# @param targets [Array[String]] The targets to run on.
|
121
|
+
# @return [Bolt::ResultSet]
|
122
|
+
#
|
123
|
+
def upload_file(source, destination, targets)
|
124
|
+
source = find_file(source)
|
125
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
126
|
+
|
127
|
+
Bolt::Util.validate_file('source file', source, true)
|
128
|
+
|
129
|
+
with_benchmark do
|
130
|
+
executor.upload_file(targets, source, destination)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Show groups in the inventory.
|
135
|
+
#
|
136
|
+
# @return [Hash]
|
137
|
+
#
|
138
|
+
def list_groups
|
139
|
+
{
|
140
|
+
count: inventory.group_names.count,
|
141
|
+
groups: inventory.group_names.sort,
|
142
|
+
inventory: {
|
143
|
+
default: config.default_inventoryfile.to_s,
|
144
|
+
source: inventory.source
|
145
|
+
}
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
# Show available guides.
|
150
|
+
#
|
151
|
+
# @param guides [Hash] A map of topics to paths to guides.
|
152
|
+
# @param outputter [Bolt::Outputter] An outputter instance.
|
153
|
+
# @return [Boolean]
|
154
|
+
#
|
155
|
+
def list_guides
|
156
|
+
{ topics: load_guides.keys }
|
157
|
+
end
|
158
|
+
|
159
|
+
# Show a guide.
|
160
|
+
#
|
161
|
+
# @param topic [String] The topic to show.
|
162
|
+
# @param guides [Hash] A map of topics to paths to guides.
|
163
|
+
# @param outputter [Bolt::Outputter] An outputter instance.
|
164
|
+
# @return [Boolean]
|
165
|
+
#
|
166
|
+
def show_guide(topic)
|
167
|
+
if (path = load_guides[topic])
|
168
|
+
analytics.event('Guide', 'known_topic', label: topic)
|
169
|
+
|
170
|
+
begin
|
171
|
+
guide = Bolt::Util.read_yaml_hash(path, 'guide')
|
172
|
+
rescue SystemCallError => e
|
173
|
+
raise Bolt::FileError("#{e.message}: unable to load guide page", filepath)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Make sure both topic and guide keys are defined
|
177
|
+
unless (%w[topic guide] - guide.keys).empty?
|
178
|
+
msg = "Guide file #{path} must have a 'topic' key and 'guide' key, but has #{guide.keys} keys."
|
179
|
+
raise Bolt::Error.new(msg, 'bolt/invalid-guide')
|
180
|
+
end
|
181
|
+
|
182
|
+
Bolt::Util.symbolize_top_level_keys(guide)
|
183
|
+
else
|
184
|
+
analytics.event('Guide', 'unknown_topic', label: topic)
|
185
|
+
raise Bolt::Error.new(
|
186
|
+
"Unknown topic '#{topic}'. For a list of available topics, run 'bolt guide'.",
|
187
|
+
'bolt/unknown-topic'
|
188
|
+
)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Show inventory information.
|
193
|
+
#
|
194
|
+
# @param targets [Array[String]] The targets to show.
|
195
|
+
# @return [Hash]
|
196
|
+
#
|
197
|
+
def show_inventory(targets = nil)
|
198
|
+
targets = group_targets_by_source(targets || ['all'])
|
199
|
+
|
200
|
+
{
|
201
|
+
adhoc: {
|
202
|
+
count: targets[:adhoc].count,
|
203
|
+
targets: targets[:adhoc].map(&:detail)
|
204
|
+
},
|
205
|
+
inventory: {
|
206
|
+
count: targets[:inventory].count,
|
207
|
+
targets: targets[:inventory].map(&:detail),
|
208
|
+
file: (inventory.source || config.default_inventoryfile).to_s,
|
209
|
+
default: config.default_inventoryfile.to_s
|
210
|
+
},
|
211
|
+
targets: targets.values.flatten.map(&:detail),
|
212
|
+
count: targets.values.flatten.count
|
213
|
+
}
|
214
|
+
end
|
215
|
+
|
216
|
+
# Lookup a value with Hiera.
|
217
|
+
#
|
218
|
+
# @param key [String] The key to look up in the hierarchy.
|
219
|
+
# @param targets [Array[String]] The targets to use as context.
|
220
|
+
# @param vars [Hash] Variables to set in the scope.
|
221
|
+
# @return [Bolt::ResultSet, String] The result of the lookup.
|
222
|
+
#
|
223
|
+
def lookup(key, targets, vars: {})
|
224
|
+
executor.publish_event(type: :plan_start, plan: nil)
|
225
|
+
|
226
|
+
with_benchmark do
|
227
|
+
pal.lookup(key,
|
228
|
+
inventory.get_targets(targets, ext_glob: true),
|
229
|
+
inventory,
|
230
|
+
executor,
|
231
|
+
plan_vars: vars)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Lookup a value with Hiera using plan_hierarchy.
|
236
|
+
#
|
237
|
+
# @param key [String] The key to lookup up in the plan_hierarchy.
|
238
|
+
# @param vars [Hash] Variables to set in the scope.
|
239
|
+
# @return [String] The result of the lookup.
|
240
|
+
#
|
241
|
+
def plan_lookup(key, vars: {})
|
242
|
+
pal.plan_hierarchy_lookup(key, plan_vars: vars)
|
243
|
+
end
|
244
|
+
|
245
|
+
# Add a new module to the project.
|
246
|
+
#
|
247
|
+
# @param name [String] The name of the module to add.
|
248
|
+
# @param outputter [Bolt::Outputter] An outputter instance.
|
249
|
+
# @return [Boolean]
|
250
|
+
#
|
251
|
+
def add_module(name, outputter)
|
252
|
+
assert_project_file(config.project)
|
253
|
+
|
254
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
255
|
+
|
256
|
+
installer.add(name,
|
257
|
+
config.project.modules,
|
258
|
+
config.project.puppetfile,
|
259
|
+
config.project.managed_moduledir,
|
260
|
+
config.project.project_file,
|
261
|
+
@plugins.resolve_references(config.module_install))
|
262
|
+
end
|
263
|
+
|
264
|
+
# Generate Puppet data types from project modules.
|
265
|
+
#
|
266
|
+
# @return [Boolean]
|
267
|
+
#
|
268
|
+
def generate_types
|
269
|
+
pal.generate_types(cache: true)
|
270
|
+
end
|
271
|
+
|
272
|
+
# Install the project's modules.
|
273
|
+
#
|
274
|
+
# @param outputter [Bolt::Outputter] An outputter instance.
|
275
|
+
# @param force [Boolean] Forcibly install modules.
|
276
|
+
# @param resolve [Boolean] Resolve module dependencies.
|
277
|
+
# @return [Boolean]
|
278
|
+
#
|
279
|
+
def install_modules(outputter, force: false, resolve: true)
|
280
|
+
assert_project_file(config.project)
|
281
|
+
|
282
|
+
if config.project.modules.empty? && resolve
|
283
|
+
outputter.print_message(
|
284
|
+
"Project configuration file #{config.project.project_file} does not "\
|
285
|
+
"specify any module dependencies. Nothing to do."
|
286
|
+
)
|
287
|
+
return true
|
288
|
+
end
|
289
|
+
|
290
|
+
installer = Bolt::ModuleInstaller.new(outputter, pal)
|
291
|
+
|
292
|
+
installer.install(config.project.modules,
|
293
|
+
config.project.puppetfile,
|
294
|
+
config.project.managed_moduledir,
|
295
|
+
@plugins.resolve_references(config.module_install),
|
296
|
+
force: force,
|
297
|
+
resolve: resolve)
|
298
|
+
end
|
299
|
+
|
300
|
+
# Show modules available to the project.
|
301
|
+
#
|
302
|
+
# @return [Hash] A map of module directories to module definitions.
|
303
|
+
#
|
304
|
+
def list_modules
|
305
|
+
pal.list_modules
|
306
|
+
end
|
307
|
+
|
308
|
+
# Show module information.
|
309
|
+
#
|
310
|
+
# @param name [String] The name of the module.
|
311
|
+
# @return [Hash] The module information.
|
312
|
+
#
|
313
|
+
def show_module(name)
|
314
|
+
pal.show_module(name)
|
315
|
+
end
|
316
|
+
|
317
|
+
# Convert a YAML plan to a Puppet language plan.
|
318
|
+
#
|
319
|
+
# @param plan [String] The plan to convert. Can be a plan name or a path.
|
320
|
+
# @return [String] The converted plan.
|
321
|
+
#
|
322
|
+
def convert_plan(plan)
|
323
|
+
pal.convert_plan(plan)
|
324
|
+
end
|
325
|
+
|
326
|
+
# Create a new project-level plan.
|
327
|
+
#
|
328
|
+
# @param name [String] The name of the new plan.
|
329
|
+
# @param puppet [Boolean] Create a Puppet language plan.
|
330
|
+
# @param plan_script [String] Reference to the script to run in the new plan.
|
331
|
+
# @return [Boolean]
|
332
|
+
#
|
333
|
+
def new_plan(name, puppet: false, plan_script: nil)
|
334
|
+
Bolt::PlanCreator.validate_plan_name(config.project, name)
|
335
|
+
|
336
|
+
if plan_script
|
337
|
+
Bolt::Util.validate_file('script', find_file(plan_script))
|
338
|
+
end
|
339
|
+
|
340
|
+
Bolt::PlanCreator.create_plan(config.project.plans_path,
|
341
|
+
name,
|
342
|
+
is_puppet: puppet,
|
343
|
+
script: plan_script)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Run a plan.
|
347
|
+
#
|
348
|
+
# @param plan [String] The plan to run.
|
349
|
+
# @param targets [Array[String], NilClass] The targets to pass to the plan.
|
350
|
+
# @param params [Hash] Parameters to pass to the plan.
|
351
|
+
# @return [Bolt::PlanResult]
|
352
|
+
#
|
353
|
+
def run_plan(plan, targets, params: {})
|
354
|
+
plan_params = pal.get_plan_info(plan)['parameters']
|
355
|
+
if targets && targets.any?
|
356
|
+
if params['nodes'] || params['targets']
|
357
|
+
key = params.include?('nodes') ? 'nodes' : 'targets'
|
358
|
+
raise Bolt::CLIError,
|
359
|
+
"A plan's '#{key}' parameter can be specified using the --#{key} option, but in that " \
|
360
|
+
"case it must not be specified as a separate #{key}=<value> parameter nor included " \
|
361
|
+
"in the JSON data passed in the --params option"
|
362
|
+
end
|
363
|
+
|
364
|
+
target_param = plan_params.dig('targets', 'type') =~ /TargetSpec/
|
365
|
+
node_param = plan_params.include?('nodes')
|
366
|
+
|
367
|
+
if node_param && target_param
|
368
|
+
msg = "Plan parameters include both 'nodes' and 'targets' with type 'TargetSpec', " \
|
369
|
+
"neither will populated with the value for --nodes or --targets."
|
370
|
+
Bolt::Logger.warn("nodes_targets_parameters", msg)
|
371
|
+
elsif node_param
|
372
|
+
params['nodes'] = targets.join(',')
|
373
|
+
elsif target_param
|
374
|
+
params['targets'] = targets.join(',')
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
sensitive_params = params.keys.select { |param| plan_params.dig(param, 'sensitive') }
|
379
|
+
|
380
|
+
plan_context = { plan_name: plan, params: params, sensitive: sensitive_params }
|
381
|
+
|
382
|
+
executor.start_plan(plan_context)
|
383
|
+
result = pal.run_plan(plan, params, executor, inventory, plugins.puppetdb_client)
|
384
|
+
executor.finish_plan(result)
|
385
|
+
|
386
|
+
result
|
387
|
+
rescue Bolt::Error => e
|
388
|
+
Bolt::PlanResult.new(e, 'failure')
|
389
|
+
end
|
390
|
+
|
391
|
+
# Show plan information.
|
392
|
+
#
|
393
|
+
# @param plan [String] The name of the plan to show.
|
394
|
+
# @return [Hash]
|
395
|
+
#
|
396
|
+
def show_plan(plan)
|
397
|
+
pal.get_plan_info(plan)
|
398
|
+
end
|
399
|
+
|
400
|
+
# List plans available to the project.
|
401
|
+
#
|
402
|
+
# @param filter [String] A substring to filter plans by.
|
403
|
+
# @return [Hash]
|
404
|
+
#
|
405
|
+
def list_plans(filter: nil)
|
406
|
+
{
|
407
|
+
plans: filter_content(pal.list_plans_with_cache(filter_content: true), filter),
|
408
|
+
modulepath: pal.user_modulepath
|
409
|
+
}
|
410
|
+
end
|
411
|
+
|
412
|
+
# Show available plugins.
|
413
|
+
#
|
414
|
+
# @return [Hash]
|
415
|
+
#
|
416
|
+
def list_plugins
|
417
|
+
{ plugins: plugins.list_plugins, modulepath: pal.user_modulepath }
|
418
|
+
end
|
419
|
+
|
420
|
+
# Applies one or more policies to the specified targets.
|
421
|
+
#
|
422
|
+
# @param policies [String] A comma-separated list of policies to apply.
|
423
|
+
# @param targets [Array[String]] The list of targets to apply the policies to.
|
424
|
+
# @param noop [Boolean] Whether to apply the policies in no-operation mode.
|
425
|
+
# @return [Bolt::ResultSet]
|
426
|
+
#
|
427
|
+
def apply_policies(policies, targets, noop: false)
|
428
|
+
policies = policies.split(',')
|
429
|
+
|
430
|
+
# Validate that the policies are available to the project.
|
431
|
+
unavailable_policies = policies.reject do |policy|
|
432
|
+
@config.policies&.any? do |known_policy|
|
433
|
+
File.fnmatch?(known_policy, policy, File::FNM_EXTGLOB)
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
if unavailable_policies.any?
|
438
|
+
command = Bolt::Util.powershell? ? 'Get-BoltPolicy' : 'bolt policy show'
|
439
|
+
|
440
|
+
# CODEREVIEW: Phrasing
|
441
|
+
raise Bolt::Error.new(
|
442
|
+
"The following policies are not available to the project: '#{unavailable_policies.join("', '")}'. "\
|
443
|
+
"You must list policies in a project's 'policies' setting before Bolt can apply them to targets. "\
|
444
|
+
"For a list of policies available to the project, run '#{command}'.",
|
445
|
+
'bolt/unavailable-policy-error'
|
446
|
+
)
|
447
|
+
end
|
448
|
+
|
449
|
+
# Validate that the policies are loadable Puppet classes.
|
450
|
+
unloadable_policies = []
|
451
|
+
|
452
|
+
@pal.in_catalog_compiler do |_|
|
453
|
+
environment = Puppet.lookup(:current_environment)
|
454
|
+
|
455
|
+
unloadable_policies = policies.reject do |policy|
|
456
|
+
environment.known_resource_types.find_hostclass(policy)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
# CODEREVIEW: Phrasing
|
461
|
+
if unloadable_policies.any?
|
462
|
+
raise Bolt::Error.new(
|
463
|
+
"The following policies cannot be loaded: '#{unloadable_policies.join("', '")}'. "\
|
464
|
+
"Policies must be a Puppet class saved to a project's or module's manifests directory.",
|
465
|
+
'bolt/unloadable-policy-error'
|
466
|
+
)
|
467
|
+
end
|
468
|
+
|
469
|
+
# Execute a single include statement with all the policies to apply them
|
470
|
+
# to the targets. Yay, reusable code!
|
471
|
+
apply(nil, targets, code: "include #{policies.join(', ')}", noop: noop)
|
472
|
+
end
|
473
|
+
|
474
|
+
# Add a new policy to the project.
|
475
|
+
#
|
476
|
+
# @param name [String] The name of the new policy.
|
477
|
+
# @return [Hash]
|
478
|
+
#
|
479
|
+
def new_policy(name)
|
480
|
+
# Validate the policy name
|
481
|
+
unless name =~ Bolt::Module::CONTENT_NAME_REGEX
|
482
|
+
message = <<~MESSAGE.chomp
|
483
|
+
Invalid policy name '#{name}'. Policy names are composed of one or more name segments
|
484
|
+
separated by double colons '::'.
|
485
|
+
|
486
|
+
Each name segment must begin with a lowercase letter, and can only include lowercase
|
487
|
+
letters, digits, and underscores.
|
488
|
+
|
489
|
+
Examples of valid policy names:
|
490
|
+
- #{@config.project.name}
|
491
|
+
- #{@config.project.name}::my_policy
|
492
|
+
MESSAGE
|
493
|
+
|
494
|
+
raise Bolt::ValidationError, message
|
495
|
+
end
|
496
|
+
|
497
|
+
# Validate that we're not running with the default project
|
498
|
+
if @config.project.name.nil?
|
499
|
+
command = Bolt::Util.powershell? ? 'New-BoltProject -Name <NAME>' : 'bolt project init <NAME>'
|
500
|
+
message = <<~MESSAGE.chomp
|
501
|
+
Can't create a policy for the default Bolt project because it doesn't
|
502
|
+
have a name. Run '#{command}' to create a new project.
|
503
|
+
MESSAGE
|
504
|
+
raise Bolt::ValidationError, message
|
505
|
+
end
|
506
|
+
|
507
|
+
prefix, *name_segments, basename = name.split('::')
|
508
|
+
|
509
|
+
# Error if name is not namespaced to project
|
510
|
+
unless prefix == @config.project.name
|
511
|
+
raise Bolt::ValidationError,
|
512
|
+
"Policy name '#{name}' must begin with project name '#{@config.project.name}'. Did "\
|
513
|
+
"you mean '#{@config.project.name}::#{name}'?"
|
514
|
+
end
|
515
|
+
|
516
|
+
# If the policy name is just the project name, use the special init.pp class
|
517
|
+
basename ||= 'init'
|
518
|
+
|
519
|
+
# Policies can be saved in subdirectories in the 'manifests/' directory
|
520
|
+
policy_dir = File.expand_path(File.join(name_segments), @config.project.manifests)
|
521
|
+
policy = File.expand_path("#{basename}.pp", policy_dir)
|
522
|
+
|
523
|
+
# Ensure the policy does not already exist
|
524
|
+
if File.exist?(policy)
|
525
|
+
raise Bolt::Error.new(
|
526
|
+
"A policy with the name '#{name}' already exists at '#{policy}', nothing to do.",
|
527
|
+
'bolt/existing-policy-error'
|
528
|
+
)
|
529
|
+
end
|
530
|
+
|
531
|
+
# Create the policy directory structure in the current project
|
532
|
+
begin
|
533
|
+
FileUtils.mkdir_p(policy_dir)
|
534
|
+
rescue Errno::EEXIST => e
|
535
|
+
raise Bolt::Error.new(
|
536
|
+
"#{e.message}; unable to create manifests directory '#{policy_dir}'",
|
537
|
+
'bolt/existing-file-error'
|
538
|
+
)
|
539
|
+
end
|
540
|
+
|
541
|
+
# Create the new policy
|
542
|
+
begin
|
543
|
+
File.write(policy, <<~POLICY)
|
544
|
+
class #{name} {
|
545
|
+
|
546
|
+
}
|
547
|
+
POLICY
|
548
|
+
rescue Errno::EACCES => e
|
549
|
+
raise Bolt::FileError.new("#{e.message}; unable to create policy", policy)
|
550
|
+
end
|
551
|
+
|
552
|
+
# Update the project configuration to include the new policy
|
553
|
+
project_config = Bolt::Util.read_yaml_hash(@config.project.project_file, 'project config')
|
554
|
+
|
555
|
+
# Add the 'policies' key if it does not exist and de-dupiclate entries
|
556
|
+
project_config['policies'] ||= []
|
557
|
+
project_config['policies'] << name
|
558
|
+
project_config['policies'].uniq!
|
559
|
+
|
560
|
+
begin
|
561
|
+
File.write(@config.project.project_file, project_config.to_yaml)
|
562
|
+
rescue Errno::EACCES => e
|
563
|
+
raise Bolt::FileError.new(
|
564
|
+
"#{e.message}; unable to update project configuration",
|
565
|
+
@config.project.project_file
|
566
|
+
)
|
567
|
+
end
|
568
|
+
|
569
|
+
{ name: name, path: policy }
|
570
|
+
end
|
571
|
+
|
572
|
+
# List policies available to the project.
|
573
|
+
#
|
574
|
+
# @return [Hash]
|
575
|
+
#
|
576
|
+
def list_policies
|
577
|
+
unless @config.policies
|
578
|
+
command = Bolt::Util.powershell? ? 'New-BoltPolicy -Name <NAME>' : 'bolt policy new <NAME>'
|
579
|
+
|
580
|
+
raise Bolt::Error.new(
|
581
|
+
"Project configuration file #{@config.project.project_file} does not "\
|
582
|
+
"specify any policies. You can add policies to the project by including "\
|
583
|
+
"a 'policies' key or creating a new policy using the '#{command}' "\
|
584
|
+
"command.",
|
585
|
+
'bolt/no-policies-error'
|
586
|
+
)
|
587
|
+
end
|
588
|
+
|
589
|
+
{ policies: @config.policies.uniq, modulepath: pal.user_modulepath }
|
590
|
+
end
|
591
|
+
|
592
|
+
# Initialize the current directory as a Bolt project.
|
593
|
+
#
|
594
|
+
# @param name [String] The name of the project.
|
595
|
+
# @param [Bolt::Outputter] An outputter instance.
|
596
|
+
# @param modules [Array[String], NilClass] Modules to install.
|
597
|
+
# @return [Boolean]
|
598
|
+
#
|
599
|
+
def create_project(name, outputter, modules: nil)
|
600
|
+
Bolt::ProjectManager.new(config, outputter, pal)
|
601
|
+
.create(Dir.pwd, name, modules)
|
602
|
+
end
|
603
|
+
|
604
|
+
# Migrate a project to current best practices.
|
605
|
+
#
|
606
|
+
# @param [Bolt::Outputter] An outputter instance.
|
607
|
+
# @return [Boolean]
|
608
|
+
#
|
609
|
+
def migrate_project(outputter)
|
610
|
+
Bolt::ProjectManager.new(config, outputter, pal).migrate
|
611
|
+
end
|
612
|
+
|
613
|
+
# Run a script on a list of targets.
|
614
|
+
#
|
615
|
+
# @param script [String] The path to the script to run.
|
616
|
+
# @param targets [Array[String]] The targets to run on.
|
617
|
+
# @param arguments [Array[String], NilClass] Arguments to pass to the script.
|
618
|
+
# @param env_vars [Hash] Environment variables to set on the target.
|
619
|
+
# @return [Bolt::ResultSet]
|
620
|
+
#
|
621
|
+
def run_script(script, targets, arguments: [], env_vars: nil)
|
622
|
+
script = find_file(script)
|
623
|
+
|
624
|
+
Bolt::Util.validate_file('script', script)
|
625
|
+
|
626
|
+
with_benchmark do
|
627
|
+
executor.run_script(inventory.get_targets(targets, ext_glob: true),
|
628
|
+
script,
|
629
|
+
arguments,
|
630
|
+
env_vars: env_vars)
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
# Generate a keypair using the configured secret plugin.
|
635
|
+
#
|
636
|
+
# @param force [Boolean] Forcibly create a keypair.
|
637
|
+
# @param plugin [String] The secret plugin to use.
|
638
|
+
# @return [Boolean]
|
639
|
+
#
|
640
|
+
def create_secret_keys(force: false, plugin: 'pkcs7')
|
641
|
+
unless plugins.by_name(plugin)
|
642
|
+
raise Bolt::Plugin::PluginError::Unknown, plugin
|
643
|
+
end
|
644
|
+
|
645
|
+
plugins.get_hook(plugin, :secret_createkeys)
|
646
|
+
.call('force' => force)
|
647
|
+
end
|
648
|
+
|
649
|
+
# Decrypt ciphertext using the configured secret plugin.
|
650
|
+
#
|
651
|
+
# @param ciphertext [String] The ciphertext to decrypt.
|
652
|
+
# @param plugin [String] The secret plugin to use.
|
653
|
+
# @return [Boolean]
|
654
|
+
#
|
655
|
+
def decrypt_secret(ciphertext, plugin: 'pkcs7')
|
656
|
+
unless plugins.by_name(plugin)
|
657
|
+
raise Bolt::Plugin::PluginError::Unknown, plugin
|
658
|
+
end
|
659
|
+
|
660
|
+
plugins.get_hook(plugin, :secret_decrypt)
|
661
|
+
.call('encrypted_value' => ciphertext)
|
662
|
+
end
|
663
|
+
|
664
|
+
# Encrypt plaintext using the configured secret plugin.
|
665
|
+
#
|
666
|
+
# @param plaintext [String] The plaintext to encrypt.
|
667
|
+
# @param plugin [String] The secret plugin to use.
|
668
|
+
# @return [Boolean]
|
669
|
+
#
|
670
|
+
def encrypt_secret(plaintext, plugin: 'pkcs7')
|
671
|
+
unless plugins.by_name(plugin)
|
672
|
+
raise Bolt::Plugin::PluginError::Unknown, plugin
|
673
|
+
end
|
674
|
+
|
675
|
+
plugins.get_hook(plugin, :secret_encrypt)
|
676
|
+
.call('plaintext_value' => plaintext)
|
677
|
+
end
|
678
|
+
|
679
|
+
# Run a task on a list of targets.
|
680
|
+
#
|
681
|
+
# @param task [String] The name of the task.
|
682
|
+
# @param options [Hash] Additional options.
|
683
|
+
# @return [Bolt::ResultSet]
|
684
|
+
#
|
685
|
+
def run_task(task, targets, params: {})
|
686
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
687
|
+
|
688
|
+
with_benchmark do
|
689
|
+
pal.run_task(task, targets, params, executor, inventory)
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
# Show task information.
|
694
|
+
#
|
695
|
+
# @param task [String] The name of the task to show.
|
696
|
+
# @return [Hash]
|
697
|
+
#
|
698
|
+
def show_task(task)
|
699
|
+
{ task: pal.get_task(task) }
|
700
|
+
end
|
701
|
+
|
702
|
+
# List available tasks.
|
703
|
+
#
|
704
|
+
# @param filter [String] A substring to filter tasks by.
|
705
|
+
# @return [Hash]
|
706
|
+
#
|
707
|
+
def list_tasks(filter: nil)
|
708
|
+
{
|
709
|
+
tasks: filter_content(pal.list_tasks_with_cache(filter_content: true), filter),
|
710
|
+
modulepath: pal.user_modulepath
|
711
|
+
}
|
712
|
+
end
|
713
|
+
|
714
|
+
# Assert that there is a project configuration file.
|
715
|
+
#
|
716
|
+
# @param project [Bolt::Project] The Bolt project.
|
717
|
+
#
|
718
|
+
private def assert_project_file(project)
|
719
|
+
unless project.project_file?
|
720
|
+
command = Bolt::Util.powershell? ? 'New-BoltProject' : 'bolt project init'
|
721
|
+
|
722
|
+
msg = "Could not find project configuration file #{project.project_file}, unable "\
|
723
|
+
"to install modules. To create a Bolt project, run '#{command}'."
|
724
|
+
|
725
|
+
raise Bolt::Error.new(msg, 'bolt/missing-project-config-error')
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
# Filter a list of content by matching substring.
|
730
|
+
#
|
731
|
+
# @param content [Hash] The content to filter.
|
732
|
+
# @param filter [String] The substring to filter content by.
|
733
|
+
#
|
734
|
+
private def filter_content(content, filter)
|
735
|
+
return content unless content && filter
|
736
|
+
content.select { |name,| name.include?(filter) }
|
737
|
+
end
|
738
|
+
|
739
|
+
# Return the path to a file. If the path is an absolute or relative path to
|
740
|
+
# a file, and the file exists, return the path as-is. Otherwise, check if
|
741
|
+
# the path is a Puppet file path and look for the file in a module's files
|
742
|
+
# directory.
|
743
|
+
#
|
744
|
+
# @param path [String] The path to the file.
|
745
|
+
#
|
746
|
+
private def find_file(path)
|
747
|
+
return path if File.exist?(path) || Pathname.new(path).absolute?
|
748
|
+
modulepath = Bolt::Config::Modulepath.new(config.modulepath)
|
749
|
+
modules = Bolt::Module.discover(modulepath.full_modulepath, config.project)
|
750
|
+
mod, file = path.split(File::SEPARATOR, 2)
|
751
|
+
|
752
|
+
if modules[mod]
|
753
|
+
logger.debug("Did not find file at #{File.expand_path(path)}, checking in module '#{mod}'")
|
754
|
+
found = Bolt::Util.find_file_in_module(modules[mod].path, file || "")
|
755
|
+
path = found.nil? ? File.join(modules[mod].path, 'files', file) : found
|
756
|
+
end
|
757
|
+
|
758
|
+
path
|
759
|
+
end
|
760
|
+
|
761
|
+
# Get a list of Bolt guides.
|
762
|
+
#
|
763
|
+
private def load_guides
|
764
|
+
root_path = File.expand_path(File.join(__dir__, '..', '..', 'guides'))
|
765
|
+
files = Dir.children(root_path).sort
|
766
|
+
|
767
|
+
files.each_with_object({}) do |file, guides|
|
768
|
+
next if file !~ /\.(yaml|yml)\z/
|
769
|
+
topic = File.basename(file, ".*")
|
770
|
+
guides[topic] = File.join(root_path, file)
|
771
|
+
end
|
772
|
+
rescue SystemCallError => e
|
773
|
+
raise Bolt::FileError.new("#{e.message}: unable to load guides directory", root_path)
|
774
|
+
end
|
775
|
+
|
776
|
+
# Return a hash of targets sorted by those that are found in the inventory
|
777
|
+
# and those that are provided on the command line.
|
778
|
+
#
|
779
|
+
# @param targets [Array[String]] The targets to group.
|
780
|
+
#
|
781
|
+
private def group_targets_by_source(targets)
|
782
|
+
# Retrieve the known group and target names. This needs to be done before
|
783
|
+
# updating targets, as that will add adhoc targets to the inventory.
|
784
|
+
known_names = inventory.target_names
|
785
|
+
targets = inventory.get_targets(targets, ext_glob: true)
|
786
|
+
|
787
|
+
inventory_targets, adhoc_targets = targets.partition do |target|
|
788
|
+
known_names.include?(target.name)
|
789
|
+
end
|
790
|
+
|
791
|
+
{ inventory: inventory_targets, adhoc: adhoc_targets }
|
792
|
+
end
|
793
|
+
|
794
|
+
# Benchmark the action and set the elapsed time on the result.
|
795
|
+
#
|
796
|
+
private def with_benchmark
|
797
|
+
result = nil
|
798
|
+
|
799
|
+
elapsed_time = Benchmark.realtime do
|
800
|
+
result = yield
|
801
|
+
end
|
802
|
+
|
803
|
+
result.tap { |r| r.elapsed_time = elapsed_time if r.is_a?(Bolt::ResultSet) }
|
804
|
+
end
|
805
|
+
end
|
806
|
+
end
|