bolt 3.14.1 → 3.15.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9dbc0b26225fd929d594a6719b55491bad8647650d257b0bbd1bf0eb2424f7c
4
- data.tar.gz: ff0df82a3a02edfbf05bdbfe39814d2d5535719dbb6b80659bfff5d28651da3a
3
+ metadata.gz: 53659858c8aae545c73cd8ef74ce2fda41c024d0040cf2c1dc935985d28d53e3
4
+ data.tar.gz: 59909ae1b57566430f66f472e453ab16341ca530b2ac3b1036a4deefd269564e
5
5
  SHA512:
6
- metadata.gz: 61a484916431f7da5b3fa8992641bdf382f0d34eaf2f054e41638e27dc48b7118c07f7729a54246a0d6e19e2a74cedc549fdcc513ba26651f84b470f2c7b187e
7
- data.tar.gz: d5bf6f496c13253e83dd7d9625058846000a5b339a13fd8d6d922b61ed57b61618125c5de76377f1e01d946e16bd220313659cc066ec793527a2c03013264bc0
6
+ metadata.gz: 6e76fe56e10409ce22d1a849adf3bbbce19c838dfbb6cb3bb8461f7a642c150a9a17beac13a08f4273ebcbf781ee0d63dd3db6b7a034a2f15d9f300a94a8a16d
7
+ data.tar.gz: c109c02ee6fb38a0ffae8abc57709d60952c8a158edb45774344ae44df3a3d6689385924eddaefea40ed437ab7d73455d8aebf2a59c81ff7c7bce5651abdde68
@@ -8,16 +8,18 @@ require 'bolt/task'
8
8
  # installed using either the configured plugin or the `task` plugin with the
9
9
  # `puppet_agent::install` task.
10
10
  #
11
- # Agent installation will be skipped if the target includes the `puppet-agent` feature, either as a
12
- # property of its transport (PCP) or by explicitly setting it as a feature in Bolt's inventory.
11
+ # Agent installation will be skipped if the target includes the `puppet-agent`
12
+ # feature, either as a property of its transport (PCP) or by explicitly setting
13
+ # it as a feature in Bolt's inventory.
13
14
  #
14
15
  # > **Note:** Not available in apply block
15
16
  Puppet::Functions.create_function(:apply_prep) do
16
17
  # @param targets A pattern or array of patterns identifying a set of targets.
17
18
  # @param options Options hash.
19
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
18
20
  # @option options [Array] _required_modules An array of modules to sync to the target.
19
21
  # @option options [String] _run_as User to run as using privilege escalation.
20
- # @return [nil]
22
+ # @return [Bolt::ResultSet]
21
23
  # @example Prepare targets by name.
22
24
  # apply_prep('target1,target2')
23
25
  dispatch :apply_prep do
@@ -25,138 +27,169 @@ Puppet::Functions.create_function(:apply_prep) do
25
27
  optional_param 'Hash[String, Data]', :options
26
28
  end
27
29
 
28
- def script_compiler
29
- @script_compiler ||= Puppet::Pal::ScriptCompiler.new(closure_scope.compiler)
30
- end
30
+ def apply_prep(target_spec, options = {})
31
+ unless Puppet[:tasks]
32
+ raise Puppet::ParseErrorWithIssue
33
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'apply_prep')
34
+ end
31
35
 
32
- def inventory
33
- @inventory ||= Puppet.lookup(:bolt_inventory)
34
- end
36
+ options = options.slice(*%w[_catch_errors _required_modules _run_as])
37
+ targets = inventory.get_targets(target_spec)
35
38
 
36
- def get_task(name, params = {})
37
- tasksig = script_compiler.task_signature(name)
38
- raise Bolt::Error.new("Task '#{name}' could not be found", 'bolt/apply-prep') unless tasksig
39
+ executor.report_function_call(self.class.name)
39
40
 
40
- errors = []
41
- unless tasksig.runnable_with?(params) { |msg| errors << msg }
42
- # This relies on runnable with printing a partial message before the first real error
43
- raise Bolt::ValidationError, "Invalid parameters for #{errors.join("\n")}"
41
+ executor.log_action('install puppet and gather facts', targets) do
42
+ executor.without_default_logging do
43
+ install_results = install_agents(targets, options)
44
+ facts_results = get_facts(install_results.ok_set.targets, options)
45
+
46
+ Bolt::ResultSet.new(install_results.error_set.results + facts_results.results)
47
+ end
44
48
  end
49
+ end
45
50
 
46
- Bolt::Task.from_task_signature(tasksig)
51
+ def applicator
52
+ @applicator ||= Puppet.lookup(:apply_executor)
47
53
  end
48
54
 
49
- # rubocop:disable Naming/AccessorMethodName
50
- def set_agent_feature(target)
51
- inventory.set_feature(target, 'puppet-agent')
55
+ def executor
56
+ @executor ||= Puppet.lookup(:bolt_executor)
52
57
  end
53
- # rubocop:enable Naming/AccessorMethodName
54
58
 
59
+ def inventory
60
+ @inventory ||= Puppet.lookup(:bolt_inventory)
61
+ end
62
+
63
+ # Runs a task. This method is called by the puppet_library hook.
64
+ #
55
65
  def run_task(targets, task, args = {}, options = {})
56
66
  executor.run_task(targets, task, args, options)
57
67
  end
58
68
 
59
- # Returns true if the target has the puppet-agent feature defined, either from inventory or transport.
60
- def agent?(target, executor, inventory)
69
+ # Returns true if the target has the puppet-agent feature defined, either from
70
+ # inventory or transport.
71
+ #
72
+ private def agent?(target)
61
73
  inventory.features(target).include?('puppet-agent') ||
62
- executor.transport(target.transport).provided_features.include?('puppet-agent') || target.remote?
74
+ executor.transport(target.transport).provided_features.include?('puppet-agent') ||
75
+ target.remote?
63
76
  end
64
77
 
65
- def executor
66
- @executor ||= Puppet.lookup(:bolt_executor)
78
+ # Generate the plugin tarball.
79
+ #
80
+ private def build_plugin_tarball(required_modules)
81
+ if required_modules.any?
82
+ Puppet.debug("Syncing only required modules: #{required_modules.join(',')}.")
83
+ end
84
+
85
+ tarball = applicator.build_plugin_tarball do |mod|
86
+ next unless required_modules.empty? || required_modules.include?(mod.name)
87
+ search_dirs = []
88
+ search_dirs << mod.plugins if mod.plugins?
89
+ search_dirs << mod.pluginfacts if mod.pluginfacts?
90
+ search_dirs
91
+ end
92
+
93
+ Puppet::Pops::Types::PSensitiveType::Sensitive.new(tarball)
67
94
  end
68
95
 
69
- def apply_prep(target_spec, options = {})
70
- unless Puppet[:tasks]
71
- raise Puppet::ParseErrorWithIssue
72
- .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'apply_prep')
96
+ # Install the puppet-agent package on targets that need it.
97
+ #
98
+ private def install_agents(targets, options)
99
+ results = []
100
+
101
+ agent_targets, agentless_targets = targets.partition { |target| agent?(target) }
102
+
103
+ agent_targets.each do |target|
104
+ Puppet.debug("Puppet Agent feature declared for #{target}")
105
+ results << Bolt::Result.new(target)
73
106
  end
74
107
 
75
- # Unfreeze this
76
- options = options.slice(*%w[_run_as _required_modules])
108
+ unless agentless_targets.empty?
109
+ hooks, errors = get_hooks(agentless_targets, options)
110
+ hook_results = run_hooks(hooks)
77
111
 
78
- applicator = Puppet.lookup(:apply_executor)
112
+ hook_results.each do |result|
113
+ next unless result.ok?
114
+ inventory.set_feature(result.target, 'puppet-agent')
115
+ end
79
116
 
80
- executor.report_function_call(self.class.name)
117
+ results.concat(hook_results).concat(errors)
118
+ end
81
119
 
82
- targets = inventory.get_targets(target_spec)
120
+ Bolt::ResultSet.new(results).tap do |resultset|
121
+ unless resultset.ok? || options['_catch_errors']
122
+ raise Bolt::RunFailure.new(resultset.error_set, 'apply_prep')
123
+ end
124
+ end
125
+ end
83
126
 
84
- required_modules = options.delete('_required_modules').to_a
85
- if required_modules.any?
86
- Puppet.debug("Syncing only required modules: #{required_modules.join(',')}.")
127
+ # Retrieve facts from each target and add them to inventory.
128
+ #
129
+ private def get_facts(targets, options)
130
+ return Bolt::ResultSet.new([]) unless targets.any?
131
+
132
+ task = applicator.custom_facts_task
133
+ args = { 'plugins' => build_plugin_tarball(options.delete('_required_modules').to_a) }
134
+ results = run_task(targets, task, args, options)
135
+
136
+ unless results.ok? || options['_catch_errors']
137
+ raise Bolt::RunFailure.new(results, 'run_task', task.name)
87
138
  end
88
139
 
89
- # Gather facts, including custom facts
90
- plugins = applicator.build_plugin_tarball do |mod|
91
- next unless required_modules.empty? || required_modules.include?(mod.name)
92
- search_dirs = []
93
- search_dirs << mod.plugins if mod.plugins?
94
- search_dirs << mod.pluginfacts if mod.pluginfacts?
95
- search_dirs
140
+ results.each do |result|
141
+ next unless result.ok?
142
+
143
+ if unsupported_puppet?(result['clientversion'])
144
+ Bolt::Logger.deprecate(
145
+ "unsupported_puppet",
146
+ "Detected unsupported Puppet agent version #{result['clientversion']} on target "\
147
+ "#{result.target}. Bolt supports Puppet agent 6.0.0 and higher."
148
+ )
149
+ end
150
+
151
+ inventory.add_facts(result.target, result.value)
96
152
  end
97
153
 
98
- executor.log_action('install puppet and gather facts', targets) do
99
- executor.without_default_logging do
100
- # Skip targets that include the puppet-agent feature, as we know an agent will be available.
101
- agent_targets, need_install_targets = targets.partition { |target| agent?(target, executor, inventory) }
102
- agent_targets.each { |target| Puppet.debug "Puppet Agent feature declared for #{target.name}" }
103
- unless need_install_targets.empty?
104
- # lazy-load expensive gem code
105
- require 'concurrent'
106
- pool = Concurrent::ThreadPoolExecutor.new
107
-
108
- hooks = need_install_targets.map do |t|
109
- opts = t.plugin_hooks&.fetch('puppet_library').dup
110
- plugin_name = opts.delete('plugin')
111
- hook = inventory.plugins.get_hook(plugin_name, :puppet_library)
112
- # Give plan function options precedence over inventory options
113
- { 'target' => t,
114
- 'hook_proc' => hook.call(opts.merge(options), t, self) }
115
- rescue StandardError => e
116
- Bolt::Result.from_exception(t, e)
117
- end
118
-
119
- hook_errors, ok_hooks = hooks.partition { |h| h.is_a?(Bolt::Result) }
120
-
121
- futures = ok_hooks.map do |hash|
122
- Concurrent::Future.execute(executor: pool) do
123
- hash['hook_proc'].call
124
- end
125
- end
126
-
127
- results = futures.zip(ok_hooks).map do |f, hash|
128
- f.value || Bolt::Result.from_exception(hash['target'], f.reason)
129
- end
130
- set = Bolt::ResultSet.new(results + hook_errors)
131
- raise Bolt::RunFailure.new(set.error_set, 'apply_prep') unless set.ok
132
-
133
- need_install_targets.each { |target| set_agent_feature(target) }
134
- end
135
-
136
- task = applicator.custom_facts_task
137
- arguments = { 'plugins' => Puppet::Pops::Types::PSensitiveType::Sensitive.new(plugins) }
138
- results = run_task(targets, task, arguments, options)
139
-
140
- # TODO: Standardize RunFailure type with error above
141
- raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok?
142
-
143
- results.each do |result|
144
- # Log a warning if the client version is < 6
145
- if unsupported_puppet?(result['clientversion'])
146
- Bolt::Logger.deprecate(
147
- "unsupported_puppet",
148
- "Detected unsupported Puppet agent version #{result['clientversion']} on target "\
149
- "#{result.target}. Bolt supports Puppet agent 6.0.0 and higher."
150
- )
151
- end
152
-
153
- inventory.add_facts(result.target, result.value)
154
- end
154
+ results
155
+ end
156
+
157
+ # Return a list of targets and their puppet_library hooks.
158
+ #
159
+ private def get_hooks(targets, options)
160
+ hooks = []
161
+ errors = []
162
+
163
+ targets.each do |target|
164
+ plugin_opts = target.plugin_hooks.fetch('puppet_library').dup
165
+ plugin_name = plugin_opts.delete('plugin')
166
+ hook = inventory.plugins.get_hook(plugin_name, :puppet_library)
167
+
168
+ hooks << { 'target' => target,
169
+ 'proc' => hook.call(plugin_opts.merge(options), target, self) }
170
+ rescue StandardError => e
171
+ errors << Bolt::Result.from_exception(target, e)
172
+ end
173
+
174
+ [hooks, errors]
175
+ end
176
+
177
+ # Runs the puppet_library hook for each target, returning the result
178
+ # of each.
179
+ #
180
+ private def run_hooks(hooks)
181
+ require 'concurrent'
182
+ pool = Concurrent::ThreadPoolExecutor.new
183
+
184
+ futures = hooks.map do |hook|
185
+ Concurrent::Future.execute(executor: pool) do
186
+ hook['proc'].call
155
187
  end
156
188
  end
157
189
 
158
- # Return nothing
159
- nil
190
+ futures.zip(hooks).map do |future, hook|
191
+ future.value || Bolt::Result.from_exception(hook['target'], future.reason)
192
+ end
160
193
  end
161
194
 
162
195
  # Returns true if the client's major version is < 6.
@@ -0,0 +1,27 @@
1
+ ---
2
+ topic: debugging
3
+ guide: |
4
+ When Bolt isn't behaving as expected, there are a few helpful commands and
5
+ logs that can help identify common issues. The first place to look is in
6
+ `<PROJECT>/bolt-debug.log`, which contains debug-level logs from the last Bolt
7
+ run. This log file includes where the Bolt project was loaded from, the
8
+ location of any configuration or inventory files that were loaded, and the
9
+ modulepath that modules were loaded from.
10
+
11
+ If you're having issues with loading targets or target configuration, you
12
+ can see the list of resolved Bolt target names by running `bolt inventory
13
+ show` on *nix systems or `Get-BoltInventory` in PowerShell. To see the
14
+ resolved configuration for each target, run the command with the `--detail` or
15
+ `-Detail` options.
16
+
17
+ Lastly, if you're having trouble loading Bolt content you can use `bolt
18
+ module show` on *nix systems or `Get-BoltModule` in PowerShell to see the list
19
+ of loaded modules, including where they were loaded from. You can also use
20
+ `bolt task show` or `Get-BoltTask` to list loaded tasks, and `bolt plan show`
21
+ or `Get-BoltPlan` to list loaded plans.
22
+
23
+ Visit the linked documentation for more in-depth troubleshooting help for
24
+ specific issues.
25
+
26
+ documentation:
27
+ - https://pup.pt/bolt-troubleshooting
@@ -0,0 +1,23 @@
1
+ ---
2
+ topic: inventory
3
+ guide: |
4
+ The inventory describes the targets that you run Bolt commands on, along
5
+ with any data and configuration for the targets. Targets in an inventory can
6
+ belong to one or more groups, allowing you to share data and configuration
7
+ across multiple targets and to specify multiple targets for your Bolt
8
+ commands without the need to list each target individually.
9
+
10
+ In most cases, Bolt loads the inventory from an inventory file in your Bolt
11
+ project. The inventory file is a YAML file named 'inventory.yaml'. Because
12
+ Bolt loads the inventory file from a Bolt project, you must have an existing
13
+ project configuration file named 'bolt-project.yaml' alongside the inventory
14
+ file.
15
+
16
+ When Bolt loads inventory, it loads the entire inventory, not just the
17
+ groups and targets specified on the command line. If you've defined a
18
+ target in multiple groups, this might result in target configuration that
19
+ is different than expected.
20
+
21
+ documentation:
22
+ - https://pup.pt/bolt-inventory
23
+ - https://pup.pt/bolt-inventory-reference
data/guides/links.yaml ADDED
@@ -0,0 +1,12 @@
1
+ ---
2
+ topic: links
3
+ guide: |
4
+ Bolt documentation https://bolt.guide
5
+ Ask a question in #bolt https://slack.puppet.com/
6
+ Contribute at https://github.com/puppetlabs/bolt/
7
+ Getting Started Guide https://pup.pt/bolt-getting-started
8
+ Reference Documentation https://pup.pt/bolt-reference
9
+ Troubleshooting Bolt https://pup.pt/bolt-troubleshooting
10
+ Bolt Developer Updates https://pup.pt/bolt-dev-updates
11
+ Bolt Changelog https://pup.pt/bolt-changelog
12
+ Bolt Examples https://pup.pt/bolt-examples
@@ -0,0 +1,17 @@
1
+ ---
2
+ topic: logging
3
+ guide: |
4
+ Bolt prints messages both to the console and to log files. Messages can
5
+ either come from Bolt's 'outputter', which logs user-facing messages like
6
+ progress and results, or from the 'logger', which logs warnings, errors, and
7
+ log-structured output to log files. Both of these message streams are
8
+ configurable.
9
+
10
+ By default, Bolt logs to the console at 'warn' level and writes a log file to
11
+ '<project>/bolt-debug.log' at 'debug' level. Unless you are running a plan,
12
+ Bolt runs in verbose mode by default.
13
+
14
+ To learn more about projects, see the 'project' guide.
15
+
16
+ documentation:
17
+ - https://pup.pt/bolt-logging
@@ -0,0 +1,18 @@
1
+ ---
2
+ topic: module
3
+ guide: |
4
+ Modules are shareable, reusable packages of Puppet content. They can include
5
+ tasks, plans, functions, and other types of content that you can use in your
6
+ project. You can download and install modules to your project from the
7
+ Puppet Forge or write your own modules. Bolt also ships with several helpful
8
+ modules pre-installed that are available to all of your projects.
9
+
10
+ Bolt makes it easy to manage the modules that your project depends on. You
11
+ can use Bolt commands to install a project's modules, add new modules to a
12
+ project, and view the modules that are available to the project.
13
+
14
+ To learn more about managing modules in a project, see the documentation.
15
+ To learn how modules are loaded by Bolt, see the 'modulepath' guide.
16
+
17
+ documentation:
18
+ - https://pup.pt/bolt-modules
@@ -0,0 +1,24 @@
1
+ ---
2
+ topic: modulepath
3
+ guide: |
4
+ The modulepath is an ordered list of directories that Bolt loads modules
5
+ from. When Bolt runs a command, it automatically loads modules from the
6
+ modulepath.
7
+
8
+ While Bolt has a default modulepath, you can also configure your own
9
+ modulepath, which can include directories within the project or directories
10
+ elsewhere on your system. Regardless of whether your project uses a default
11
+ or configured modulepath, Bolt automatically adds directories to the
12
+ modulepath. This includes modules containing core Bolt content, which is
13
+ added to the beginning of the modulepath, and bundled content, which is
14
+ added to the end of the modulepath.
15
+
16
+ Modules loaded from a directory listed earlier in the modulepath take
17
+ precedence over modules with the same name loaded from a directory later in
18
+ the modulepath. Bolt will not warn or error when two modules share a name
19
+ and instead will ignore modules with a lower precedence.
20
+
21
+ To learn more about modules, see the 'module' guide.
22
+
23
+ documentation:
24
+ - https://pup.pt/bolt-project-reference#modulepath
@@ -0,0 +1,21 @@
1
+ ---
2
+ topic: project
3
+ guide: |
4
+ A Bolt project is a directory that serves as the launching point for Bolt
5
+ and allows you to create a shareable orchestration application. Projects
6
+ typically include a project configuration file, an inventory file, and any
7
+ content you use in your project workflow, such as tasks and plans.
8
+
9
+ When you run Bolt, it runs in the context of a project. If the directory you
10
+ run Bolt from is not a project, Bolt attempts to find a project by
11
+ traversing the parent directories. If Bolt is unable to find a project, it
12
+ runs from the default project, located at '~/.puppetlabs/bolt'.
13
+
14
+ A directory is only considered a Bolt project when it has a project
15
+ configuration file named 'bolt-project.yaml'. Bolt doesn't load project data
16
+ and content, including inventory files, unless the data and content are part
17
+ of a project.
18
+
19
+ documentation:
20
+ - https://pup.pt/bolt-projects
21
+ - https://pup.pt/bolt-project-reference
@@ -0,0 +1,28 @@
1
+ ---
2
+ topic: targets
3
+ guide: |
4
+ A target is a device that Bolt connects to and runs actions on. Targets can
5
+ be physical, such as servers, or virtual, such as containers or virtual
6
+ machines.
7
+
8
+ Several of Bolt's commands connect to targets and run actions on them.
9
+ These commands require a target or targets to run on. You can specify
10
+ targets to a command using one of the following command-line options:
11
+
12
+ *nix options Powershell options
13
+ -t, --targets TARGETS -T, -Targets TARGETS
14
+ -q, --query QUERY -Q, -Query QUERY
15
+ --rerun FILTER -Rerun FILTER
16
+
17
+ The 'targets' option accepts a comma-separated list of target URIs or group
18
+ names, or can read a target list from an input file '@<file>' or stdin '-'.
19
+ URIs can be specified with the format [protocol://][user@]host[:port]. To
20
+ learn more about available protocols and their defaults, run 'bolt guide
21
+ transports'.
22
+
23
+ Typically, targets and their configuration and data are listed in a
24
+ project's inventory file. For more information about inventory files,
25
+ see 'bolt guide inventory'.
26
+
27
+ documentation:
28
+ - https://pup.pt/bolt-commands
@@ -0,0 +1,22 @@
1
+ ---
2
+ topic: transports
3
+ guide: |
4
+ Bolt uses transports (also known as protocols) to establish a connection
5
+ with a target in order to run actions on the target. The default transport is
6
+ SSH, and you can see available transports along with their configuration
7
+ options and defaults at http://pup.pt/bolt-reference.
8
+
9
+ You can specify a transport for a target by prepending '<transport>://' to
10
+ the target's URI. For example, to connect to a target with hostname
11
+ 'example.com' as user 'Administrator' using the WinRM transport, you would
12
+ pass the following to the target flag:
13
+ winrm://Administrator@example.com
14
+
15
+ You can also specify a default transport for all targets by passing the
16
+ '--transport' flag on *nix systems and the '-Transport' flag in Powershell.
17
+ Finally, you can set the transport for a target in the inventory. For more
18
+ information about the Bolt inventory, run 'bolt guide inventory'.
19
+
20
+ documentation:
21
+ - https://pup.pt/bolt-commands#specify-a-transport
22
+ - http://pup.pt/bolt-inventory#transport-configuration
@@ -1095,7 +1095,7 @@ module Bolt
1095
1095
  @options[:log] = { 'console' => { 'level' => level } }
1096
1096
  end
1097
1097
  define('--clear-cache',
1098
- "Clear plugin cache before executing.") do |_|
1098
+ "Clear plugin, plan, and task caches before executing.") do |_|
1099
1099
  @options[:clear_cache] = true
1100
1100
  end
1101
1101
  define('--plugin PLUGIN', 'Select the plugin to use.') do |plug|
data/lib/bolt/cli.rb CHANGED
@@ -238,8 +238,10 @@ module Bolt
238
238
  config.check_path_case('modulepath', config.modulepath)
239
239
  config.project.check_deprecated_file
240
240
 
241
- if options[:clear_cache] && File.exist?(config.project.plugin_cache_file)
242
- FileUtils.rm(config.project.plugin_cache_file)
241
+ if options[:clear_cache]
242
+ FileUtils.rm(config.project.plugin_cache_file) if File.exist?(config.project.plugin_cache_file)
243
+ FileUtils.rm(config.project.task_cache_file) if File.exist?(config.project.task_cache_file)
244
+ FileUtils.rm(config.project.plan_cache_file) if File.exist?(config.project.plan_cache_file)
243
245
  end
244
246
 
245
247
  warn_inventory_overrides_cli(options)
@@ -836,13 +838,16 @@ module Bolt
836
838
 
837
839
  results = nil
838
840
  elapsed_time = Benchmark.realtime do
839
- pal.in_plan_compiler(executor, inventory, puppetdb_client) do |compiler|
840
- compiler.call_function('apply_prep', targets)
841
+ apply_prep_results = pal.in_plan_compiler(executor, inventory, puppetdb_client) do |compiler|
842
+ compiler.call_function('apply_prep', targets, '_catch_errors' => true)
841
843
  end
842
844
 
843
- results = pal.with_bolt_executor(executor, inventory, puppetdb_client) do
844
- Puppet.lookup(:apply_executor).apply_ast(ast, targets, catch_errors: true, noop: noop)
845
+ apply_results = pal.with_bolt_executor(executor, inventory, puppetdb_client) do
846
+ Puppet.lookup(:apply_executor)
847
+ .apply_ast(ast, apply_prep_results.ok_set.targets, catch_errors: true, noop: noop)
845
848
  end
849
+
850
+ results = Bolt::ResultSet.new(apply_prep_results.error_set.results + apply_results.results)
846
851
  end
847
852
 
848
853
  executor.shutdown
data/lib/bolt/pal.rb CHANGED
@@ -447,7 +447,7 @@ module Bolt
447
447
  # @param mtime [String] The last time the file was modified.
448
448
  #
449
449
  private def file_modified?(path, mtime)
450
- path && !(File.exist?(path) && File.mtime(path).to_s == mtime)
450
+ path && !(File.exist?(path) && File.mtime(path).to_s == mtime.to_s)
451
451
  end
452
452
 
453
453
  def list_plans(filter_content: false)
@@ -512,19 +512,14 @@ module Bolt
512
512
  end
513
513
  end
514
514
 
515
- privie = plan.tag(:private)&.text
516
- unless privie.nil? || %w[true false].include?(privie.downcase)
517
- msg = "Plan #{plan_name} key 'private' must be a boolean, received: #{privie}"
518
- raise Bolt::Error.new(msg, 'bolt/invalid-plan')
519
- end
520
-
521
515
  pp_info = {
522
516
  'name' => plan_name,
523
517
  'description' => description,
524
518
  'parameters' => parameters,
525
- 'module' => mod
519
+ 'module' => mod,
520
+ 'private' => private_plan?(plan)
526
521
  }
527
- pp_info.merge!({ 'private' => privie&.downcase == 'true' }) unless privie.nil?
522
+
528
523
  pp_info.merge!(get_plan_mtime(plan.file)) if with_mtime
529
524
  pp_info
530
525
 
@@ -554,14 +549,39 @@ module Bolt
554
549
  'name' => plan_name,
555
550
  'description' => plan.description,
556
551
  'parameters' => parameters,
557
- 'module' => mod
552
+ 'module' => mod,
553
+ 'private' => !!plan.private
558
554
  }
559
- yaml_info.merge!({ 'private' => plan.private }) unless plan.private.nil?
555
+
560
556
  yaml_info.merge!(get_plan_mtime(yaml_path)) if with_mtime
561
557
  yaml_info
562
558
  end
563
559
  end
564
560
 
561
+ # Returns true if the plan is private, false otherwise.
562
+ #
563
+ # @param plan [PuppetStrings::Yard::CodeObjects::Plan] The puppet-strings plan documentation.
564
+ # @return [Boolean]
565
+ #
566
+ private def private_plan?(plan)
567
+ if plan.tag(:private)
568
+ value = plan.tag(:private).text
569
+ api_value = value.downcase == 'true' ? 'private' : 'public'
570
+
571
+ Bolt::Logger.deprecate(
572
+ 'plan_private_tag',
573
+ "Tag '@private #{value}' in plan '#{plan.name}' is deprecated, use '@api #{api_value}' instead"
574
+ )
575
+
576
+ unless %w[true false].include?(plan.tag(:private).text.downcase)
577
+ msg = "Value for '@private' tag in plan '#{plan.name}' must be a boolean, received: #{value}"
578
+ raise Bolt::Error.new(msg, 'bolt/invalid-plan')
579
+ end
580
+ end
581
+
582
+ plan.tag(:api).text == 'private' || plan.tag(:private)&.text&.downcase == 'true'
583
+ end
584
+
565
585
  def get_plan_mtime(path)
566
586
  # If the plan is from the project modules/ directory, or is in the
567
587
  # project itself, include the last mtime of the file so we can compare
@@ -30,7 +30,7 @@ module Bolt
30
30
  plan_string = String.new('')
31
31
  plan_string << "# #{plan_object.description}\n" if plan_object.description
32
32
  plan_string << "# WARNING: This is an autogenerated plan. It might not behave as expected.\n"
33
- plan_string << "# @private #{plan_object.private}\n" unless plan_object.private.nil?
33
+ plan_string << "# @api #{plan_object.private ? 'private' : 'public'}\n" unless plan_object.private.nil?
34
34
  plan_string << "#{param_descriptions}\n" unless param_descriptions.empty?
35
35
 
36
36
  plan_string << "plan #{plan_object.name}("
@@ -59,7 +59,7 @@ module Bolt
59
59
  run_opts = {}
60
60
  run_opts[:run_as] = opts['_run_as'] if opts['_run_as']
61
61
  begin
62
- task = apply_prep.get_task(opts['task'], params)
62
+ task = @context.get_validated_task(opts['task'], params)
63
63
  rescue Bolt::Error => e
64
64
  raise Bolt::Plugin::PluginError::ExecutionError.new(e.message, name, 'puppet_library')
65
65
  end
data/lib/bolt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '3.14.1'
4
+ VERSION = '3.15.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.14.1
4
+ version: 3.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-26 00:00:00.000000000 Z
11
+ date: 2021-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -466,6 +466,15 @@ files:
466
466
  - bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb
467
467
  - bolt-modules/system/lib/puppet/functions/system/env.rb
468
468
  - exe/bolt
469
+ - guides/debugging.yaml
470
+ - guides/inventory.yaml
471
+ - guides/links.yaml
472
+ - guides/logging.yaml
473
+ - guides/module.yaml
474
+ - guides/modulepath.yaml
475
+ - guides/project.yaml
476
+ - guides/targets.yaml
477
+ - guides/transports.yaml
469
478
  - lib/bolt.rb
470
479
  - lib/bolt/analytics.rb
471
480
  - lib/bolt/applicator.rb