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.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/Puppetfile +52 -0
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +60 -0
  4. data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +51 -0
  5. data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
  6. data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +71 -0
  7. data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +55 -0
  8. data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +65 -0
  9. data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +93 -0
  10. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +33 -0
  11. data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +38 -0
  12. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +208 -0
  13. data/bolt-modules/boltlib/lib/puppet/functions/background.rb +62 -0
  14. data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +57 -0
  15. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +130 -0
  16. data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +31 -0
  17. data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +52 -0
  18. data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +87 -0
  19. data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +34 -0
  20. data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +35 -0
  21. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +74 -0
  22. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +97 -0
  23. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +47 -0
  24. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +52 -0
  25. data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +40 -0
  26. data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +42 -0
  27. data/bolt-modules/boltlib/lib/puppet/functions/resource.rb +53 -0
  28. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +106 -0
  29. data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
  30. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +291 -0
  31. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +145 -0
  32. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +164 -0
  33. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +211 -0
  34. data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +48 -0
  35. data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +43 -0
  36. data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +145 -0
  37. data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +38 -0
  38. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +101 -0
  39. data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +29 -0
  40. data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +131 -0
  41. data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +59 -0
  42. data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +39 -0
  43. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +50 -0
  44. data/bolt-modules/boltlib/types/planresult.pp +18 -0
  45. data/bolt-modules/boltlib/types/targetspec.pp +7 -0
  46. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +42 -0
  47. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +20 -0
  48. data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
  49. data/bolt-modules/file/lib/puppet/functions/file/delete.rb +21 -0
  50. data/bolt-modules/file/lib/puppet/functions/file/exists.rb +28 -0
  51. data/bolt-modules/file/lib/puppet/functions/file/join.rb +20 -0
  52. data/bolt-modules/file/lib/puppet/functions/file/read.rb +33 -0
  53. data/bolt-modules/file/lib/puppet/functions/file/readable.rb +28 -0
  54. data/bolt-modules/file/lib/puppet/functions/file/write.rb +24 -0
  55. data/bolt-modules/log/lib/puppet/functions/log/debug.rb +39 -0
  56. data/bolt-modules/log/lib/puppet/functions/log/error.rb +40 -0
  57. data/bolt-modules/log/lib/puppet/functions/log/fatal.rb +40 -0
  58. data/bolt-modules/log/lib/puppet/functions/log/info.rb +39 -0
  59. data/bolt-modules/log/lib/puppet/functions/log/trace.rb +39 -0
  60. data/bolt-modules/log/lib/puppet/functions/log/warn.rb +41 -0
  61. data/bolt-modules/out/lib/puppet/functions/out/message.rb +36 -0
  62. data/bolt-modules/out/lib/puppet/functions/out/verbose.rb +35 -0
  63. data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
  64. data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +65 -0
  65. data/bolt-modules/system/lib/puppet/functions/system/env.rb +20 -0
  66. data/exe/bolt +17 -0
  67. data/guides/debugging.yaml +27 -0
  68. data/guides/inventory.yaml +23 -0
  69. data/guides/links.yaml +12 -0
  70. data/guides/logging.yaml +17 -0
  71. data/guides/module.yaml +18 -0
  72. data/guides/modulepath.yaml +24 -0
  73. data/guides/project.yaml +21 -0
  74. data/guides/targets.yaml +28 -0
  75. data/guides/transports.yaml +22 -0
  76. data/lib/bolt/analytics.rb +233 -0
  77. data/lib/bolt/application.rb +806 -0
  78. data/lib/bolt/applicator.rb +368 -0
  79. data/lib/bolt/apply_inventory.rb +93 -0
  80. data/lib/bolt/apply_result.rb +154 -0
  81. data/lib/bolt/apply_target.rb +90 -0
  82. data/lib/bolt/bolt_option_parser.rb +1226 -0
  83. data/lib/bolt/catalog/logging.rb +15 -0
  84. data/lib/bolt/catalog.rb +144 -0
  85. data/lib/bolt/cli.rb +949 -0
  86. data/lib/bolt/config/modulepath.rb +30 -0
  87. data/lib/bolt/config/options.rb +673 -0
  88. data/lib/bolt/config/transport/base.rb +133 -0
  89. data/lib/bolt/config/transport/docker.rb +34 -0
  90. data/lib/bolt/config/transport/jail.rb +33 -0
  91. data/lib/bolt/config/transport/local.rb +39 -0
  92. data/lib/bolt/config/transport/lxd.rb +34 -0
  93. data/lib/bolt/config/transport/options.rb +431 -0
  94. data/lib/bolt/config/transport/orch.rb +41 -0
  95. data/lib/bolt/config/transport/podman.rb +33 -0
  96. data/lib/bolt/config/transport/remote.rb +24 -0
  97. data/lib/bolt/config/transport/ssh.rb +138 -0
  98. data/lib/bolt/config/transport/winrm.rb +63 -0
  99. data/lib/bolt/config.rb +515 -0
  100. data/lib/bolt/container_result.rb +105 -0
  101. data/lib/bolt/error.rb +194 -0
  102. data/lib/bolt/executor.rb +539 -0
  103. data/lib/bolt/fiber_executor.rb +190 -0
  104. data/lib/bolt/inventory/group.rb +446 -0
  105. data/lib/bolt/inventory/inventory.rb +391 -0
  106. data/lib/bolt/inventory/options.rb +139 -0
  107. data/lib/bolt/inventory/target.rb +293 -0
  108. data/lib/bolt/inventory.rb +120 -0
  109. data/lib/bolt/logger.rb +252 -0
  110. data/lib/bolt/module.rb +54 -0
  111. data/lib/bolt/module_installer/installer.rb +44 -0
  112. data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
  113. data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
  114. data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
  115. data/lib/bolt/module_installer/puppetfile.rb +131 -0
  116. data/lib/bolt/module_installer/resolver.rb +129 -0
  117. data/lib/bolt/module_installer/specs/forge_spec.rb +91 -0
  118. data/lib/bolt/module_installer/specs/git_spec.rb +150 -0
  119. data/lib/bolt/module_installer/specs/id/base.rb +116 -0
  120. data/lib/bolt/module_installer/specs/id/gitclone.rb +120 -0
  121. data/lib/bolt/module_installer/specs/id/github.rb +90 -0
  122. data/lib/bolt/module_installer/specs/id/gitlab.rb +92 -0
  123. data/lib/bolt/module_installer/specs.rb +95 -0
  124. data/lib/bolt/module_installer.rb +208 -0
  125. data/lib/bolt/node/errors.rb +55 -0
  126. data/lib/bolt/node/output.rb +29 -0
  127. data/lib/bolt/outputter/human.rb +958 -0
  128. data/lib/bolt/outputter/json.rb +205 -0
  129. data/lib/bolt/outputter/logger.rb +76 -0
  130. data/lib/bolt/outputter/rainbow.rb +118 -0
  131. data/lib/bolt/outputter.rb +57 -0
  132. data/lib/bolt/pal/issues.rb +19 -0
  133. data/lib/bolt/pal/logging.rb +17 -0
  134. data/lib/bolt/pal/yaml_plan/evaluator.rb +83 -0
  135. data/lib/bolt/pal/yaml_plan/loader.rb +94 -0
  136. data/lib/bolt/pal/yaml_plan/parameter.rb +63 -0
  137. data/lib/bolt/pal/yaml_plan/step/command.rb +45 -0
  138. data/lib/bolt/pal/yaml_plan/step/download.rb +37 -0
  139. data/lib/bolt/pal/yaml_plan/step/eval.rb +42 -0
  140. data/lib/bolt/pal/yaml_plan/step/message.rb +31 -0
  141. data/lib/bolt/pal/yaml_plan/step/plan.rb +42 -0
  142. data/lib/bolt/pal/yaml_plan/step/resources.rb +170 -0
  143. data/lib/bolt/pal/yaml_plan/step/script.rb +62 -0
  144. data/lib/bolt/pal/yaml_plan/step/task.rb +42 -0
  145. data/lib/bolt/pal/yaml_plan/step/upload.rb +37 -0
  146. data/lib/bolt/pal/yaml_plan/step/verbose.rb +31 -0
  147. data/lib/bolt/pal/yaml_plan/step.rb +223 -0
  148. data/lib/bolt/pal/yaml_plan/transpiler.rb +90 -0
  149. data/lib/bolt/pal/yaml_plan.rb +172 -0
  150. data/lib/bolt/pal.rb +847 -0
  151. data/lib/bolt/plan_creator.rb +219 -0
  152. data/lib/bolt/plan_future.rb +86 -0
  153. data/lib/bolt/plan_result.rb +44 -0
  154. data/lib/bolt/plugin/cache.rb +76 -0
  155. data/lib/bolt/plugin/env_var.rb +54 -0
  156. data/lib/bolt/plugin/module.rb +276 -0
  157. data/lib/bolt/plugin/prompt.rb +36 -0
  158. data/lib/bolt/plugin/puppet_connect_data.rb +84 -0
  159. data/lib/bolt/plugin/puppetdb.rb +124 -0
  160. data/lib/bolt/plugin/task.rb +72 -0
  161. data/lib/bolt/plugin.rb +380 -0
  162. data/lib/bolt/project.rb +219 -0
  163. data/lib/bolt/project_manager/config_migrator.rb +113 -0
  164. data/lib/bolt/project_manager/inventory_migrator.rb +67 -0
  165. data/lib/bolt/project_manager/migrator.rb +39 -0
  166. data/lib/bolt/project_manager/module_migrator.rb +203 -0
  167. data/lib/bolt/project_manager.rb +221 -0
  168. data/lib/bolt/puppetdb/client.rb +153 -0
  169. data/lib/bolt/puppetdb/config.rb +176 -0
  170. data/lib/bolt/puppetdb/instance.rb +146 -0
  171. data/lib/bolt/puppetdb.rb +15 -0
  172. data/lib/bolt/r10k_log_proxy.rb +30 -0
  173. data/lib/bolt/rerun.rb +55 -0
  174. data/lib/bolt/resource_instance.rb +133 -0
  175. data/lib/bolt/result.rb +247 -0
  176. data/lib/bolt/result_set.rb +128 -0
  177. data/lib/bolt/shell/bash/tmpdir.rb +62 -0
  178. data/lib/bolt/shell/bash.rb +516 -0
  179. data/lib/bolt/shell/powershell/snippets.rb +181 -0
  180. data/lib/bolt/shell/powershell.rb +365 -0
  181. data/lib/bolt/shell.rb +105 -0
  182. data/lib/bolt/target.rb +174 -0
  183. data/lib/bolt/task/puppet_server.rb +27 -0
  184. data/lib/bolt/task/run.rb +55 -0
  185. data/lib/bolt/task.rb +163 -0
  186. data/lib/bolt/transport/base.rb +252 -0
  187. data/lib/bolt/transport/docker/connection.rb +150 -0
  188. data/lib/bolt/transport/docker.rb +23 -0
  189. data/lib/bolt/transport/jail/connection.rb +81 -0
  190. data/lib/bolt/transport/jail.rb +21 -0
  191. data/lib/bolt/transport/local/connection.rb +106 -0
  192. data/lib/bolt/transport/local.rb +20 -0
  193. data/lib/bolt/transport/lxd/connection.rb +115 -0
  194. data/lib/bolt/transport/lxd.rb +26 -0
  195. data/lib/bolt/transport/orch/connection.rb +111 -0
  196. data/lib/bolt/transport/orch.rb +271 -0
  197. data/lib/bolt/transport/podman/connection.rb +102 -0
  198. data/lib/bolt/transport/podman.rb +19 -0
  199. data/lib/bolt/transport/remote.rb +41 -0
  200. data/lib/bolt/transport/simple.rb +54 -0
  201. data/lib/bolt/transport/ssh/connection.rb +321 -0
  202. data/lib/bolt/transport/ssh/exec_connection.rb +140 -0
  203. data/lib/bolt/transport/ssh.rb +48 -0
  204. data/lib/bolt/transport/winrm/connection.rb +378 -0
  205. data/lib/bolt/transport/winrm.rb +33 -0
  206. data/lib/bolt/util/format.rb +68 -0
  207. data/lib/bolt/util/puppet_log_level.rb +21 -0
  208. data/lib/bolt/util.rb +465 -0
  209. data/lib/bolt/validator.rb +227 -0
  210. data/lib/bolt/version.rb +5 -0
  211. data/lib/bolt.rb +8 -0
  212. data/lib/bolt_server/acl.rb +39 -0
  213. data/lib/bolt_server/base_config.rb +112 -0
  214. data/lib/bolt_server/config.rb +64 -0
  215. data/lib/bolt_server/file_cache.rb +200 -0
  216. data/lib/bolt_server/request_error.rb +11 -0
  217. data/lib/bolt_server/schemas/action-check_node_connections.json +14 -0
  218. data/lib/bolt_server/schemas/action-run_command.json +12 -0
  219. data/lib/bolt_server/schemas/action-run_script.json +47 -0
  220. data/lib/bolt_server/schemas/action-run_task.json +20 -0
  221. data/lib/bolt_server/schemas/action-upload_file.json +47 -0
  222. data/lib/bolt_server/schemas/partials/target-any.json +10 -0
  223. data/lib/bolt_server/schemas/partials/target-ssh.json +88 -0
  224. data/lib/bolt_server/schemas/partials/target-winrm.json +67 -0
  225. data/lib/bolt_server/schemas/partials/task.json +94 -0
  226. data/lib/bolt_server/schemas/transport-ssh.json +25 -0
  227. data/lib/bolt_server/schemas/transport-winrm.json +19 -0
  228. data/lib/bolt_server/transport_app.rb +554 -0
  229. data/lib/bolt_spec/bolt_context.rb +226 -0
  230. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +51 -0
  231. data/lib/bolt_spec/plans/action_stubs/download_stub.rb +66 -0
  232. data/lib/bolt_spec/plans/action_stubs/plan_stub.rb +55 -0
  233. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +59 -0
  234. data/lib/bolt_spec/plans/action_stubs/task_stub.rb +57 -0
  235. data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +65 -0
  236. data/lib/bolt_spec/plans/action_stubs.rb +196 -0
  237. data/lib/bolt_spec/plans/mock_executor.rb +361 -0
  238. data/lib/bolt_spec/plans/publish_stub.rb +49 -0
  239. data/lib/bolt_spec/plans.rb +190 -0
  240. data/lib/bolt_spec/run.rb +246 -0
  241. data/lib/logging_extensions/logging.rb +13 -0
  242. data/libexec/apply_catalog.rb +130 -0
  243. data/libexec/bolt_catalog +68 -0
  244. data/libexec/custom_facts.rb +63 -0
  245. data/libexec/query_resources.rb +75 -0
  246. data/modules/aggregate/lib/puppet/functions/aggregate/count.rb +21 -0
  247. data/modules/aggregate/lib/puppet/functions/aggregate/nodes.rb +22 -0
  248. data/modules/aggregate/lib/puppet/functions/aggregate/targets.rb +21 -0
  249. data/modules/aggregate/plans/count.pp +56 -0
  250. data/modules/aggregate/plans/targets.pp +56 -0
  251. data/modules/canary/lib/puppet/functions/canary/merge.rb +13 -0
  252. data/modules/canary/lib/puppet/functions/canary/random_split.rb +22 -0
  253. data/modules/canary/lib/puppet/functions/canary/skip.rb +25 -0
  254. data/modules/canary/plans/init.pp +100 -0
  255. data/modules/puppet_connect/plans/test_input_data.pp +94 -0
  256. data/modules/puppetdb_fact/plans/init.pp +20 -0
  257. data/resources/bolt_bash_completion.sh +214 -0
  258. metadata +735 -0
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+ require 'bolt/pal'
5
+ require 'bolt/task'
6
+
7
+ # Runs a given instance of a `Task` on the given set of targets and returns the result from each.
8
+ # This function does nothing if the list of targets is empty.
9
+ #
10
+ # > **Note:** Not available in apply block
11
+ Puppet::Functions.create_function(:run_task) do
12
+ # Run a task.
13
+ # @param task_name The task to run.
14
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
15
+ # @param args A hash of arguments to the task. Can also include additional options.
16
+ # @option args [Boolean] _catch_errors Whether to catch raised errors.
17
+ # @option args [String] _run_as User to run as using privilege escalation.
18
+ # @option args [Boolean] _noop Run the task in noop mode if available.
19
+ # @return A list of results, one entry per target.
20
+ # @example Run a task as root
21
+ # run_task('facts', $targets, '_run_as' => 'root')
22
+ dispatch :run_task do
23
+ param 'String[1]', :task_name
24
+ param 'Boltlib::TargetSpec', :targets
25
+ optional_param 'Hash[String[1], Any]', :args
26
+ return_type 'ResultSet'
27
+ end
28
+
29
+ # Run a task, logging the provided description.
30
+ # @param task_name The task to run.
31
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
32
+ # @param description A description to be output when calling this function.
33
+ # @param args A hash of arguments to the task. Can also include additional options.
34
+ # @option args [Boolean] _catch_errors Whether to catch raised errors.
35
+ # @option args [String] _run_as User to run as using privilege escalation.
36
+ # @option args [Boolean] _noop Run the task in noop mode if available.
37
+ # @return A list of results, one entry per target.
38
+ # @example Run a task
39
+ # run_task('facts', $targets, 'Gather OS facts')
40
+ dispatch :run_task_with_description do
41
+ param 'String[1]', :task_name
42
+ param 'Boltlib::TargetSpec', :targets
43
+ param 'Optional[String]', :description
44
+ optional_param 'Hash[String[1], Any]', :args
45
+ return_type 'ResultSet'
46
+ end
47
+
48
+ def run_task(task_name, targets, args = {})
49
+ run_task_with_description(task_name, targets, nil, args)
50
+ end
51
+
52
+ def run_task_with_description(task_name, targets, description, args = {})
53
+ unless Puppet[:tasks]
54
+ raise Puppet::ParseErrorWithIssue
55
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'run_task')
56
+ end
57
+
58
+ options, params = args.partition { |k, _v| k.start_with?('_') }.map(&:to_h)
59
+ options = options.transform_keys { |k| k.sub(/^_/, '').to_sym }
60
+ options[:description] = description if description
61
+
62
+ executor = Puppet.lookup(:bolt_executor)
63
+ inventory = Puppet.lookup(:bolt_inventory)
64
+
65
+ # Bolt calls this function internally to trigger tasks from the CLI. We
66
+ # don't want to count those invocations.
67
+ unless options[:bolt_api_call]
68
+ # Send Analytics Report
69
+ executor.report_function_call(self.class.name)
70
+ end
71
+
72
+ # Report Analytics for bundled content, this should capture tasks run from
73
+ # both CLI and Plans.
74
+ executor.report_bundled_content('Task', task_name)
75
+
76
+ # Ensure that given targets are all Target instances.
77
+ targets = inventory.get_targets(targets)
78
+
79
+ # Return early if there are no targets.
80
+ if targets.empty?
81
+ return Bolt::ResultSet.new([])
82
+ end
83
+
84
+ # If all targets use the PCP transport, create a fake task instead of
85
+ # loading the actual task definition.
86
+ if targets.all? { |t| t.transport == 'pcp' }
87
+ task = Bolt::Task.new(task_name,
88
+ { 'supports_noop' => true },
89
+ [{ 'name' => '', 'path' => '' }])
90
+ else
91
+ # TODO: use the compiler injection once PUP-8237 lands
92
+ task_signature = Puppet::Pal::ScriptCompiler.new(closure_scope.compiler).task_signature(task_name)
93
+ if task_signature.nil?
94
+ raise Bolt::Error.unknown_task(task_name)
95
+ end
96
+
97
+ task = Bolt::Task.from_task_signature(task_signature)
98
+
99
+ # Set the default value for any params that have one and were not provided
100
+ # or are undef.
101
+ params = task.parameter_defaults.merge(params) do |_, default, passed|
102
+ passed.nil? ? default : passed
103
+ end
104
+
105
+ task_signature.runnable_with?(params) do |mismatch_message|
106
+ raise with_stack(:TYPE_MISMATCH, mismatch_message)
107
+ end || (raise with_stack(:TYPE_MISMATCH, 'Task parameters do not match'))
108
+ end
109
+
110
+ # Generate a helpful error message about the type-mismatch between the type
111
+ # Data and the actual type of params.
112
+ unless Puppet::Pops::Types::TypeFactory.data.instance?(params)
113
+ params_t = Puppet::Pops::Types::TypeCalculator.infer_set(params)
114
+ desc = Puppet::Pops::Types::TypeMismatchDescriber.singleton.describe_mismatch(
115
+ 'Task parameters are not of type Data. run_task()',
116
+ Puppet::Pops::Types::TypeFactory.data, params_t
117
+ )
118
+ raise with_stack(:TYPE_NOT_DATA, desc)
119
+ end
120
+
121
+ # Wrap parameters marked with '"sensitive": true' in the task metadata with a
122
+ # Sensitive wrapper type. This way it's not shown in logs.
123
+ if (param_spec = task.parameters)
124
+ params.each do |k, v|
125
+ if param_spec[k] && param_spec[k]['sensitive']
126
+ params[k] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(v)
127
+ end
128
+ end
129
+ end
130
+
131
+ # executor.noop is set when run task is called from the CLI
132
+ # options[:noop] is set when it's called from a plan
133
+ if executor.noop || options[:noop]
134
+ if task.supports_noop
135
+ params['_noop'] = true
136
+ else
137
+ raise with_stack(:TASK_NO_NOOP, 'Task does not support noop')
138
+ end
139
+ end
140
+
141
+ # Report whether the task was run in noop mode.
142
+ executor.report_noop_mode(executor.noop || options[:noop])
143
+
144
+ file_line = Puppet::Pops::PuppetStack.top_of_stack
145
+ result = if executor.in_parallel?
146
+ executor.run_in_thread do
147
+ executor.run_task(targets, task, params, options, file_line)
148
+ end
149
+ else
150
+ executor.run_task(targets, task, params, options, file_line)
151
+ end
152
+
153
+ if !result.ok && !options[:catch_errors]
154
+ raise Bolt::RunFailure.new(result, 'run_task', task_name)
155
+ end
156
+
157
+ result
158
+ end
159
+
160
+ def with_stack(kind, msg)
161
+ issue = Puppet::Pops::Issues.issue(kind) { msg }
162
+ Puppet::ParseErrorWithIssue.from_issue_and_stack(issue)
163
+ end
164
+ end
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+ require 'bolt/pal'
5
+ require 'bolt/task'
6
+
7
+ # Runs a given instance of a `Task` with target-specific parameters on the given set of targets and
8
+ # returns the result from each. This function differs from {run_task} by accepting a block that returns
9
+ # a `Hash` of target-specific parameters that are passed to the task. This can be used to send parameters
10
+ # based on a target's attributes, such as its `facts`, or to use conditional logic to determine the
11
+ # parameters a task should receive for a specific target.
12
+ #
13
+ # This function does nothing if the list of targets is empty.
14
+ #
15
+ # > **Note:** Not available in apply block
16
+ #
17
+ # > **Note:** Not available to targets using the pcp transport
18
+ Puppet::Functions.create_function(:run_task_with) do
19
+ # Run a task with target-specific parameters.
20
+ # @param task_name The task to run.
21
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
22
+ # @param options A hash of additional options.
23
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
24
+ # @option options [Boolean] _noop Run the task in noop mode if available.
25
+ # @option options [String] _run_as User to run as using privilege escalation.
26
+ # @param block A block that returns a `Hash` of target-specific parameters for the task.
27
+ # @return A list of results, one entry per target.
28
+ # @example Run a task with target-specific parameters as root
29
+ # run_task_with('my_task', $targets, '_run_as' => 'root') |$t| {
30
+ # { 'param1' => $t.vars['var1'],
31
+ # 'param2' => $t.vars['var2'] }
32
+ # }
33
+ dispatch :run_task_with do
34
+ param 'String[1]', :task_name
35
+ param 'Boltlib::TargetSpec', :targets
36
+ optional_param 'Hash[String[1], Any]', :options
37
+ required_block_param 'Callable[Target]', :block
38
+ return_type 'ResultSet'
39
+ end
40
+
41
+ # Run a task with target-specific parameters, logging the provided description.
42
+ # @param task_name The task to run.
43
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
44
+ # @param description A description to be output when calling this function.
45
+ # @param options A hash of additional options.
46
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
47
+ # @option options [Boolean] _noop Run the task in noop mode if available.
48
+ # @option options [String] _run_as User to run as using privilege escalation.
49
+ # @param block A block that returns a `Hash` of target-specific parameters for the task.
50
+ # @return A list of results, one entry per target.
51
+ # @example Run a task with target-specific parameters and a description
52
+ # run_task_with('my_task', $targets, 'Update system packages') |$t| {
53
+ # { 'param1' => $t.vars['var1'],
54
+ # 'param2' => $t.vars['var2'] }
55
+ # }
56
+ dispatch :run_task_with_with_description do
57
+ param 'String[1]', :task_name
58
+ param 'Boltlib::TargetSpec', :targets
59
+ param 'Optional[String]', :description
60
+ optional_param 'Hash[String[1], Any]', :options
61
+ required_block_param 'Callable[Target]', :block
62
+ return_type 'ResultSet'
63
+ end
64
+
65
+ def run_task_with(task_name, targets, options = {}, &block)
66
+ run_task_with_with_description(task_name, targets, nil, options, &block)
67
+ end
68
+
69
+ def run_task_with_with_description(task_name, targets, description, options = {})
70
+ unless Puppet[:tasks]
71
+ raise Puppet::ParseErrorWithIssue
72
+ .from_issue_and_stack(
73
+ Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
74
+ action: 'run_task_with'
75
+ )
76
+ end
77
+
78
+ executor = Puppet.lookup(:bolt_executor)
79
+ inventory = Puppet.lookup(:bolt_inventory)
80
+ error_set = []
81
+
82
+ # Report to analytics
83
+ executor.report_function_call(self.class.name)
84
+ executor.report_bundled_content('Task', task_name)
85
+
86
+ # Keep valid metaparameters, discarding everything else
87
+ options = options.select { |k, _v| k.start_with?('_') }
88
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
89
+
90
+ options[:description] = description if description
91
+
92
+ # Get all the targets
93
+ targets = Array(inventory.get_targets(targets))
94
+
95
+ # Return early if there are no targets.
96
+ if targets.empty?
97
+ return Bolt::ResultSet.new([])
98
+ end
99
+
100
+ # If all targets use the 'pcp' transport, use a fake task instead of loading the local definition
101
+ # Otherwise, load the local task definition
102
+ if (pcp_only = targets.all? { |t| t.transport == 'pcp' })
103
+ task = Bolt::Task.new(task_name,
104
+ { 'supports_noop' => true },
105
+ [{ 'name' => '', 'path' => '' }])
106
+ else
107
+ task_signature = Puppet::Pal::ScriptCompiler.new(closure_scope.compiler).task_signature(task_name)
108
+
109
+ if task_signature.nil?
110
+ raise Bolt::Error.unknown_task(task_name)
111
+ end
112
+
113
+ task = Bolt::Task.from_task_signature(task_signature)
114
+ end
115
+
116
+ # Map the targets to their specific parameters and merge with the defaults
117
+ target_mapping = targets.each_with_object({}) do |target, mapping|
118
+ params = yield(target)
119
+
120
+ # Parameters returned from the block should be a Hash. If they're not, create a failing
121
+ # Result for the target that will later be added to the ResultSet.
122
+ unless params.is_a?(Hash)
123
+ exception = with_stack(
124
+ :TYPE_MISMATCH,
125
+ "Block must return a Hash of parameters, received #{params.class}"
126
+ )
127
+ error_set << Bolt::Result.from_exception(target, exception, action: 'task')
128
+ next
129
+ end
130
+
131
+ # If parameters are mismatched, create a failing result for the target that will later
132
+ # be added to the ResultSet.
133
+ unless pcp_only
134
+ # Set the default value for any params that have one and were not provided or are undef
135
+ params = task.parameter_defaults.merge(params) do |_, default, passed|
136
+ passed.nil? ? default : passed
137
+ end
138
+
139
+ type_match = task_signature.runnable_with?(params) do |mismatch_message|
140
+ exception = with_stack(:TYPE_MISMATCH, mismatch_message)
141
+ error_set << Bolt::Result.from_exception(target, exception, action: 'task')
142
+ end
143
+
144
+ next unless type_match
145
+ end
146
+
147
+ # If there is a type mismatch between the type Data and the type of the params, create
148
+ # a failing result for the target that will later be added to the ResultSet.
149
+ unless Puppet::Pops::Types::TypeFactory.data.instance?(params)
150
+ params_t = Puppet::Pops::Types::TypeCalculator.infer_set(params)
151
+ desc = Puppet::Pops::Types::TypeMismatchDescriber.singleton.describe_mismatch(
152
+ 'Task parameters are not of type Data. run_task_with()',
153
+ Puppet::Pops::Types::TypeFactory.data, params_t
154
+ )
155
+ exception = with_stack(:TYPE_NOT_DATA, desc)
156
+ error_set << Bolt::Result.from_exception(target, exception, action: 'task')
157
+ next
158
+ end
159
+
160
+ # Wrap parameters marked with '"sensitive": true' in the task metadata with a
161
+ # Sensitive wrapper type. This way it's not shown in logs.
162
+ if (param_spec = task.parameters)
163
+ params.each do |k, v|
164
+ if param_spec[k] && param_spec[k]['sensitive']
165
+ params[k] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(v)
166
+ end
167
+ end
168
+ end
169
+
170
+ # Set the default value for any params that have one and were not provided or are undef
171
+ mapping[target] = task.parameter_defaults.merge(params) do |_, default, passed|
172
+ passed.nil? ? default : passed
173
+ end
174
+ end
175
+
176
+ # Add a noop parameter if the function was called with the noop metaparameter.
177
+ if options[:noop]
178
+ if task.supports_noop
179
+ target_mapping.each_value { |params| params['_noop'] = true }
180
+ else
181
+ raise with_stack(:TASK_NO_NOOP, 'Task does not support noop')
182
+ end
183
+ end
184
+
185
+ # Report whether the task was run in noop mode.
186
+ executor.report_noop_mode(executor.noop || options[:noop])
187
+
188
+ # Combine the results from the task run with any failing results that were
189
+ # generated earlier when creating the target mapping
190
+ file_line = Puppet::Pops::PuppetStack.top_of_stack
191
+ task_result = if executor.in_parallel?
192
+ executor.run_in_thread do
193
+ executor.run_task_with(target_mapping, task, options, file_line)
194
+ end
195
+ else
196
+ executor.run_task_with(target_mapping, task, options, file_line)
197
+ end
198
+ result = Bolt::ResultSet.new(task_result.results + error_set)
199
+
200
+ if !result.ok && !options[:catch_errors]
201
+ raise Bolt::RunFailure.new(result, 'run_task', task_name)
202
+ end
203
+
204
+ result
205
+ end
206
+
207
+ def with_stack(kind, msg)
208
+ issue = Puppet::Pops::Issues.issue(kind) { msg }
209
+ Puppet::ParseErrorWithIssue.from_issue_and_stack(issue)
210
+ end
211
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Set configuration options on a target.
6
+ #
7
+ # > **Note:** Not available in apply block
8
+ #
9
+ # > **Note:** Only compatible with inventory v2
10
+ Puppet::Functions.create_function(:set_config) do
11
+ # @param target The Target object to configure. See {get_targets}.
12
+ # @param key_or_key_path The configuration setting to update.
13
+ # @param value The configuration value
14
+ # @return The Target with the updated config
15
+ # @example Set the transport for a target
16
+ # set_config($target, 'transport', 'ssh')
17
+ # @example Set the ssh password
18
+ # set_config($target, ['ssh', 'password'], 'secret')
19
+ # @example Overwrite ssh config
20
+ # set_config($target, 'ssh', { user => 'me', password => 'secret' })
21
+ dispatch :set_config do
22
+ param 'Target', :target
23
+ param 'Variant[String, Array[String]]', :key_or_key_path
24
+ param 'Any', :value
25
+ return_type 'Target'
26
+ end
27
+
28
+ def set_config(target, key_or_key_path, value = true)
29
+ unless Puppet[:tasks]
30
+ raise Puppet::ParseErrorWithIssue
31
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'set_config')
32
+ end
33
+
34
+ inventory = Puppet.lookup(:bolt_inventory)
35
+ executor = Puppet.lookup(:bolt_executor)
36
+ # Send Analytics Report
37
+ executor.report_function_call(self.class.name)
38
+
39
+ unless inventory.version > 1
40
+ raise Puppet::ParseErrorWithIssue
41
+ .from_issue_and_stack(Bolt::PAL::Issues::UNSUPPORTED_INVENTORY_VERSION, action: 'set_config')
42
+ end
43
+
44
+ inventory.set_config(target, key_or_key_path, value)
45
+
46
+ target
47
+ end
48
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Sets a particular feature to present on a target.
6
+ #
7
+ # Features are used to determine what implementation of a task should be run.
8
+ # Supported features are:
9
+ # - `powershell`
10
+ # - `shell`
11
+ # - `puppet-agent`
12
+ #
13
+ # > **Note:** Not available in apply block
14
+ Puppet::Functions.create_function(:set_feature) do
15
+ # @param target The Target object to add features to. See {get_targets}.
16
+ # @param feature The string identifying the feature.
17
+ # @param value Whether the feature is supported.
18
+ # @return The target with the updated feature
19
+ # @example Add the `puppet-agent` feature to a target
20
+ # set_feature($target, 'puppet-agent', true)
21
+ dispatch :set_feature do
22
+ param 'Target', :target
23
+ param 'String', :feature
24
+ optional_param 'Boolean', :value
25
+ return_type 'Target'
26
+ end
27
+
28
+ def set_feature(target, feature, value = true)
29
+ unless Puppet[:tasks]
30
+ raise Puppet::ParseErrorWithIssue
31
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'set_feature')
32
+ end
33
+
34
+ inventory = Puppet.lookup(:bolt_inventory)
35
+ executor = Puppet.lookup(:bolt_executor)
36
+ # Send Analytics Report
37
+ executor.report_function_call(self.class.name)
38
+
39
+ inventory.set_feature(target, feature, value)
40
+
41
+ target
42
+ end
43
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Sets one or more ResourceInstances on a Target. This function does not apply or modify
6
+ # resources on a target.
7
+ #
8
+ # For more information about resources see [the
9
+ # documentation](https://puppet.com/docs/puppet/latest/lang_resources.html).
10
+ #
11
+ # > **Note:** The `ResourceInstance` data type is under active development and is subject to
12
+ # change. You can read more about the data type in the [experimental features
13
+ # documentation](experimental_features.md#resourceinstance-data-type).
14
+ #
15
+ # > **Note:** Not available in apply block
16
+ Puppet::Functions.create_function(:set_resources) do
17
+ # Set a single resource from a data hash.
18
+ # @param target The `Target` object to add a resource to. See {get_targets}.
19
+ # @param resource The resource data hash used to set a resource on the target.
20
+ # @return An array with the added `ResourceInstance` object.
21
+ # @example Add a resource to a target from a data hash.
22
+ # $resource_hash = {
23
+ # 'type' => File,
24
+ # 'title' => '/etc/puppetlabs',
25
+ # 'state' => { 'ensure' => 'present' }
26
+ # }
27
+ #
28
+ # $target.set_resources($resource_hash)
29
+ dispatch :set_single_resource_from_hash do
30
+ param 'Target', :target
31
+ param 'Hash', :resource
32
+ return_type 'Array[ResourceInstance]'
33
+ end
34
+
35
+ # Set a single resource from a `ResourceInstance` object
36
+ # @param target The `Target` object to add a resource to. See {get_targets}.
37
+ # @param resource The `ResourceInstance` object to set on the target.
38
+ # @return An array with the added `ResourceInstance` object.
39
+ # @example Add a resource to a target from a `ResourceInstance` object.
40
+ # $resource_instance = ResourceInstance.new(
41
+ # 'target' => $target,
42
+ # 'type' => File,
43
+ # 'title' => '/etc/puppetlabs',
44
+ # 'state' => { 'ensure' => 'present' }
45
+ # )
46
+ #
47
+ # $target.set_resources($resource_instance)
48
+ dispatch :set_single_resource_from_object do
49
+ param 'Target', :target
50
+ param 'ResourceInstance', :resource
51
+ return_type 'Array[ResourceInstance]'
52
+ end
53
+
54
+ # Set multiple resources from an array of data hashes and `ResourceInstance` objects.
55
+ # @param target The `Target` object to add resources to. See {get_targets}.
56
+ # @param resources The resource data hashes and `ResourceInstance` objects to set on the target.
57
+ # @return An array of the added `ResourceInstance` objects.
58
+ # @example Add resources from resource data hashes returned from an apply block.
59
+ # $apply_results = apply($targets) {
60
+ # File { '/etc/puppetlabs':
61
+ # ensure => present
62
+ # }
63
+ # Package { 'openssl':
64
+ # ensure => installed
65
+ # }
66
+ # }
67
+ #
68
+ # $apply_results.each |$result| {
69
+ # $result.target.set_resources($result.report['resource_statuses'].values)
70
+ # }
71
+ # @example Add resources retrieved with [`get_resources`](#get_resources) to a target.
72
+ # $resources = $target.get_resources(Package).first['resources']
73
+ # $target.set_resources($resources)
74
+ dispatch :set_resources do
75
+ param 'Target', :target
76
+ param 'Array[Variant[Hash, ResourceInstance]]', :resources
77
+ return_type 'Array[ResourceInstance]'
78
+ end
79
+
80
+ def set_single_resource_from_hash(target, resource)
81
+ set_resources(target, [resource])
82
+ end
83
+
84
+ def set_single_resource_from_object(target, resource)
85
+ set_resources(target, [resource])
86
+ end
87
+
88
+ def set_resources(target, resources)
89
+ unless Puppet[:tasks]
90
+ raise Puppet::ParseErrorWithIssue
91
+ .from_issue_and_stack(
92
+ Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
93
+ action: 'set_resources'
94
+ )
95
+ end
96
+
97
+ # Send Analytics Report
98
+ Puppet.lookup(:bolt_executor).report_function_call(self.class.name)
99
+ inventory = Puppet.lookup(:bolt_inventory)
100
+
101
+ resources.uniq.map do |resource|
102
+ if resource.is_a?(Hash)
103
+ # ResourceInstance expects a Target object, so either get a specified target from
104
+ # the inventory or use the target this function was called on.
105
+ resource_target = if resource.key?('target')
106
+ inventory.get_target(resource['target'])
107
+ else
108
+ target
109
+ end
110
+
111
+ # Observed state from get_resources() is under the 'parameters' key
112
+ resource_state = resource['state'] || resource['parameters']
113
+
114
+ # Type from apply results is under the 'resource_type' key
115
+ resource_type = resource['type'] || resource['resource_type']
116
+
117
+ init_hash = {
118
+ 'target' => resource_target,
119
+ 'type' => resource_type,
120
+ 'title' => resource['title'],
121
+ 'state' => resource_state,
122
+ 'desired_state' => resource['desired_state'],
123
+ 'events' => resource['events']
124
+ }
125
+
126
+ # Calling Bolt::ResourceInstance.new or Bolt::ResourceInstance.from_asserted_hash
127
+ # will not perform any validation on the parameters. Instead, we need to use the
128
+ # Puppet constructor to initialize the object, which will first validate the parameters
129
+ # and then call Bolt::ResourceInstance.from_asserted_hash internally. To do this we
130
+ # first need to get the Puppet datatype and then call the new function on that type.
131
+ type = Puppet::Pops::Types::TypeParser.singleton.parse('ResourceInstance')
132
+ resource = call_function('new', type, init_hash)
133
+ end
134
+
135
+ unless resource.target == target
136
+ file, line = Puppet::Pops::PuppetStack.top_of_stack
137
+ raise Bolt::ValidationError, "Cannot set resource #{resource.reference} for target "\
138
+ "#{resource.target} on target #{target}. "\
139
+ "#{Puppet::Util::Errors.error_location(file, line)}"
140
+ end
141
+
142
+ target.set_resource(resource)
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Sets a variable `{ key => value }` for a target.
6
+ #
7
+ # > **Note:** Not available in apply block
8
+ Puppet::Functions.create_function(:set_var) do
9
+ # @param target The Target object to set the variable for. See {get_targets}.
10
+ # @param key The key for the variable.
11
+ # @param value The value of the variable.
12
+ # @return The target with the updated feature
13
+ # @example Set a variable on a target
14
+ # $target.set_var('ephemeral', true)
15
+ dispatch :set_var do
16
+ param 'Target', :target
17
+ param 'String', :key
18
+ param 'Data', :value
19
+ return_type 'Target'
20
+ end
21
+
22
+ def set_var(target, key, value)
23
+ unless Puppet[:tasks]
24
+ raise Puppet::ParseErrorWithIssue
25
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'set_var')
26
+ end
27
+
28
+ inventory = Puppet.lookup(:bolt_inventory)
29
+ executor = Puppet.lookup(:bolt_executor)
30
+ # Send Analytics Report
31
+ executor.report_function_call(self.class.name)
32
+
33
+ var_hash = { key => value }
34
+ inventory.set_var(target, var_hash)
35
+
36
+ target
37
+ end
38
+ end