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,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Uploads the given file or directory to the given set of targets and returns the result from each upload.
6
+ # This function does nothing if the list of targets is empty.
7
+ #
8
+ # > **Note:** Not available in apply block
9
+ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunction) do
10
+ # Upload a file or directory.
11
+ # @param source A source path, either an absolute path or a modulename/filename selector for a
12
+ # file or directory in $MODULEROOT/files.
13
+ # @param destination An absolute path on the target(s).
14
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
15
+ # @param options A hash of additional options.
16
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
17
+ # @option options [String] _run_as User to run as using privilege escalation.
18
+ # @return A list of results, one entry per target.
19
+ # @example Upload a local file to Linux targets and change owner to 'root'
20
+ # upload_file('/var/tmp/payload.tgz', '/tmp/payload.tgz', $targets, '_run_as' => 'root')
21
+ # @example Upload a module file to a Windows target
22
+ # upload_file('postgres/default.conf', 'C:/ProgramData/postgres/default.conf', $target)
23
+ dispatch :upload_file do
24
+ scope_param
25
+ param 'String[1]', :source
26
+ param 'String[1]', :destination
27
+ param 'Boltlib::TargetSpec', :targets
28
+ optional_param 'Hash[String[1], Any]', :options
29
+ return_type 'ResultSet'
30
+ end
31
+
32
+ # Upload a file or directory, logging the provided description.
33
+ # @param source A source path, either an absolute path or a modulename/filename selector for a
34
+ # file or directory in $MODULEROOT/files.
35
+ # @param destination An absolute path on the target(s).
36
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
37
+ # @param description A description to be output when calling this function.
38
+ # @param options A hash of additional options.
39
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
40
+ # @option options [String] _run_as User to run as using privilege escalation.
41
+ # @return A list of results, one entry per target.
42
+ # @example Upload a file
43
+ # upload_file('/var/tmp/payload.tgz', '/tmp/payload.tgz', $targets, 'Uploading payload to unpack')
44
+ dispatch :upload_file_with_description do
45
+ scope_param
46
+ param 'String[1]', :source
47
+ param 'String[1]', :destination
48
+ param 'Boltlib::TargetSpec', :targets
49
+ param 'String', :description
50
+ optional_param 'Hash[String[1], Any]', :options
51
+ return_type 'ResultSet'
52
+ end
53
+
54
+ def upload_file(scope, source, destination, targets, options = {})
55
+ upload_file_with_description(scope, source, destination, targets, nil, options)
56
+ end
57
+
58
+ def upload_file_with_description(scope, source, destination, targets, description = nil, options = {})
59
+ unless Puppet[:tasks]
60
+ raise Puppet::ParseErrorWithIssue
61
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'upload_file')
62
+ end
63
+
64
+ options = options.select { |opt| opt.start_with?('_') }.transform_keys { |k| k.sub(/^_/, '').to_sym }
65
+ options[:description] = description if description
66
+
67
+ executor = Puppet.lookup(:bolt_executor)
68
+ inventory = Puppet.lookup(:bolt_inventory)
69
+
70
+ # Send Analytics Report
71
+ executor.report_function_call(self.class.name)
72
+
73
+ # Find the file path if it exists, otherwise return nil
74
+ found = Bolt::Util.find_file_from_scope(source, scope)
75
+ unless found && Puppet::FileSystem.exist?(found)
76
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
77
+ Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: source
78
+ )
79
+ end
80
+ executor.report_file_source(self.class.name, source)
81
+ # Ensure that that given targets are all Target instances
82
+ targets = inventory.get_targets(targets)
83
+ if targets.empty?
84
+ call_function('debug', "Simulating file upload of '#{found}' - no targets given - no action taken")
85
+ Bolt::ResultSet.new([])
86
+ else
87
+ file_line = Puppet::Pops::PuppetStack.top_of_stack
88
+ r = if executor.in_parallel?
89
+ executor.run_in_thread do
90
+ executor.upload_file(targets, found, destination, options, file_line)
91
+ end
92
+ else
93
+ executor.upload_file(targets, found, destination, options, file_line)
94
+ end
95
+ if !r.ok && !options[:catch_errors]
96
+ raise Bolt::RunFailure.new(r, 'upload_file', source)
97
+ end
98
+ r
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/error'
4
+
5
+ # Returns a hash of the 'vars' (variables) assigned to a target.
6
+ #
7
+ # Vars can be assigned through the inventory file or `set_var` function.
8
+ # Plan authors can call this function on a target to get the variable hash
9
+ # for that target.
10
+ Puppet::Functions.create_function(:vars) do
11
+ # @param target The Target object to get variables from. See {get_targets}.
12
+ # @return A hash of the 'vars' (variables) assigned to a target.
13
+ # @example Get vars for a target
14
+ # $target.vars
15
+ dispatch :vars do
16
+ param 'Target', :target
17
+ return_type 'Hash[String, Data]'
18
+ end
19
+
20
+ def vars(target)
21
+ inventory = Puppet.lookup(:bolt_inventory)
22
+ # Bolt executor not expected when invoked from apply block
23
+ executor = Puppet.lookup(:bolt_executor) { nil }
24
+ # Send Analytics Report
25
+ executor&.report_function_call(self.class.name)
26
+
27
+ inventory.vars(target)
28
+ end
29
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/logger'
4
+
5
+ # Wait for a Future or array of Futures to finish and return results,
6
+ # optionally with a timeout.
7
+ #
8
+ # > **Note:** Not available in apply block
9
+ Puppet::Functions.create_function(:wait, Puppet::Functions::InternalFunction) do
10
+ # Wait for Futures to finish.
11
+ # @param futures A Bolt Future object or array of Bolt Futures to wait on.
12
+ # @param options A hash of additional options.
13
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
14
+ # @return A Result or Results from the Futures
15
+ # @example Upload a large file in the background, then wait until it's loaded
16
+ # $futures = background() || {
17
+ # upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
18
+ # }
19
+ # # Run an unrelated task
20
+ # run_task("deploy", $targets)
21
+ # # Wait for the file upload to finish
22
+ # $results = wait($futures)
23
+ dispatch :wait do
24
+ param 'Variant[Future, Array[Future]]', :futures
25
+ optional_param 'Hash[String[1], Any]', :options
26
+ return_type 'Array[Boltlib::PlanResult]'
27
+ end
28
+
29
+ # Wait for all Futures in the current plan to finish.
30
+ # @param options A hash of additional options.
31
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
32
+ # @return A Result or Results from the Futures
33
+ # @example Perform multiple tasks in the background, then wait for all of them to finish
34
+ # background() || { upload_file("./large_file", "/opt/jfrog/...", $targets) }
35
+ # background() || { run_task("db::migrate", $targets) }
36
+ # # Wait for all futures in the plan to finish and return all results
37
+ # $results = wait()
38
+ dispatch :wait_for_all do
39
+ optional_param 'Hash[String[1], Any]', :options
40
+ return_type 'Array[Boltlib::PlanResult]'
41
+ end
42
+
43
+ # Wait for all Futures in the current plan to finish with a timeout.
44
+ # @param timeout How long to wait for Futures to finish before raising a Timeout error.
45
+ # @param options A hash of additional options.
46
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
47
+ # @return A Result or Results from the Futures
48
+ # @example Perform multiple tasks in the background, then wait for all of them to finish with a timeout
49
+ # background() || { upload_file("./large_file", "/opt/jfrog/...", $targets) }
50
+ # background() || { run_task("db::migrate", $targets) }
51
+ # # Wait for all futures in the plan to finish and return all results
52
+ # $results = wait(30)
53
+ dispatch :wait_for_all_with_timeout do
54
+ param 'Variant[Integer[0], Float[0.0]]', :timeout
55
+ optional_param 'Hash[String[1], Any]', :options
56
+ return_type 'Array[Boltlib::PlanResult]'
57
+ end
58
+
59
+ # Wait for Futures to finish with timeout.
60
+ # @param futures A Bolt Future object or array of Bolt Futures to wait on.
61
+ # @param timeout How long to wait for Futures to finish before raising a Timeout error.
62
+ # @param options A hash of additional options.
63
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
64
+ # @return A Result or Results from the Futures
65
+ # @example Upload a large file in the background with a 30 second timeout.
66
+ # $futures = background() || {
67
+ # upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
68
+ # }
69
+ # # Run an unrelated task
70
+ # run_task("deploy", $targets)
71
+ # # Wait for the file upload to finish
72
+ # $results = wait($futures, 30)
73
+ #
74
+ # @example Upload a large file in the background with a 30 second timeout, catching any errors.
75
+ # $futures = background() || {
76
+ # upload_file("./very_large_file", "/opt/jfrog/artifactory/var/etc/artifactory", $targets)
77
+ # }
78
+ # # Run an unrelated task
79
+ # run_task("deploy", $targets)
80
+ # # Wait for the file upload to finish
81
+ # $results = wait($futures, 30, '_catch_errors' => true)
82
+ dispatch :wait_with_timeout do
83
+ param 'Variant[Future, Array[Future]]', :futures
84
+ param 'Variant[Integer[0], Float[0.0]]', :timeout
85
+ optional_param 'Hash[String[1], Any]', :options
86
+ return_type 'Array[Boltlib::PlanResult]'
87
+ end
88
+
89
+ def wait(futures, options = {})
90
+ inner_wait(futures: futures, options: options)
91
+ end
92
+
93
+ def wait_for_all(options = {})
94
+ inner_wait(options: options)
95
+ end
96
+
97
+ def wait_for_all_with_timeout(timeout, options = {})
98
+ inner_wait(timeout: timeout, options: options)
99
+ end
100
+
101
+ def wait_with_timeout(futures, timeout, options = {})
102
+ inner_wait(futures: futures, timeout: timeout, options: options)
103
+ end
104
+
105
+ def inner_wait(futures: nil, timeout: nil, options: {})
106
+ unless Puppet[:tasks]
107
+ raise Puppet::ParseErrorWithIssue
108
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'wait')
109
+ end
110
+
111
+ valid, unknown = options.partition { |k, _v| %w[_catch_errors].include?(k) }.map(&:to_h)
112
+ if unknown.any?
113
+ file, line = Puppet::Pops::PuppetStack.top_of_stack
114
+ msg = "The wait() function call in #{file}#L#{line} received unknown options "\
115
+ "#{unknown.keys}. Removing unknown options and continuing..."
116
+ Bolt::Logger.warn("plan_function_options", msg)
117
+ end
118
+
119
+ valid = valid.transform_keys { |k| k.sub(/^_/, '').to_sym }
120
+ valid[:timeout] = timeout if timeout
121
+
122
+ executor = Puppet.lookup(:bolt_executor)
123
+ executor.report_function_call(self.class.name)
124
+
125
+ # If we get a single Future, make sure it's an array. If we didn't get any
126
+ # futures pass that on to wait so we can continue collecting any futures
127
+ # that are created while waiting on existing futures.
128
+ futures = Array(futures) unless futures.nil?
129
+ executor.wait(futures, **valid)
130
+ end
131
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt/util'
4
+
5
+ # Wait until all targets accept connections. This function allows a plan execution to wait for a customizable
6
+ # amount of time via the `wait_time` option until a target connection can be reestablished. The plan proceeds
7
+ # to the next step if the connection fails to reconnect in the time specified (default: 120 seconds). A typical
8
+ # use case for this function is if your plan reboots a remote host and the plan needs to wait for the host to reconnect
9
+ # before it continues to the next step.
10
+ #
11
+ # > **Note:** Not available in apply block
12
+ Puppet::Functions.create_function(:wait_until_available) do
13
+ # Wait until targets are available.
14
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
15
+ # @param options A hash of additional options.
16
+ # @option options [String] description A description for logging. (default: 'wait until available')
17
+ # @option options [Numeric] wait_time The time to wait, in seconds. (default: 120)
18
+ # @option options [Numeric] retry_interval The interval to wait before retrying, in seconds. (default: 1)
19
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
20
+ # @return A list of results, one entry per target. Successful results have no value.
21
+ # @example Wait for targets
22
+ # wait_until_available($targets, wait_time => 300)
23
+ dispatch :wait_until_available do
24
+ param 'Boltlib::TargetSpec', :targets
25
+ optional_param 'Hash[String[1], Any]', :options
26
+ return_type 'ResultSet'
27
+ end
28
+
29
+ def wait_until_available(targets, options = nil)
30
+ unless Puppet[:tasks]
31
+ raise Puppet::ParseErrorWithIssue
32
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
33
+ action: 'wait_until_available')
34
+ end
35
+
36
+ options ||= {}
37
+ executor = Puppet.lookup(:bolt_executor)
38
+ inventory = Puppet.lookup(:bolt_inventory)
39
+
40
+ # Send Analytics Report
41
+ executor.report_function_call(self.class.name)
42
+
43
+ # Ensure that given targets are all Target instances
44
+ targets = inventory.get_targets(targets)
45
+
46
+ if targets.empty?
47
+ call_function('debug', "Simulating wait_until_available - no targets given")
48
+ r = Bolt::ResultSet.new([])
49
+ else
50
+ opts = Bolt::Util.symbolize_top_level_keys(options.reject { |k| k == '_catch_errors' })
51
+ r = executor.wait_until_available(targets, **opts)
52
+ end
53
+
54
+ if !r.ok && !options['_catch_errors']
55
+ raise Bolt::RunFailure.new(r, 'wait_until_available')
56
+ end
57
+ r
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Define a block where default logging is suppressed.
4
+ #
5
+ # Messages for actions within this block will be logged at `info` level instead
6
+ # of `notice`, so they will not be seen normally but will still be present
7
+ # when `verbose` logging is requested.
8
+ #
9
+ # > **Note:** Not available in apply block
10
+ Puppet::Functions.create_function(:without_default_logging) do
11
+ # @param block The block where action logging is suppressed.
12
+ # @return [Undef]
13
+ # @example Suppress default logging for a series of functions
14
+ # without_default_logging() || {
15
+ # notice("Deploying on ${nodes}")
16
+ # get_targets($targets).each |$target| {
17
+ # run_task(deploy, $target)
18
+ # }
19
+ # }
20
+ dispatch :without_default_logging do
21
+ block_param 'Callable[0, 0]', :block
22
+ end
23
+
24
+ def without_default_logging
25
+ unless Puppet[:tasks]
26
+ raise Puppet::ParseErrorWithIssue
27
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
28
+ action: 'without_default_logging')
29
+ end
30
+
31
+ executor = Puppet.lookup(:bolt_executor)
32
+ # Send Analytics Report
33
+ executor.report_function_call(self.class.name)
34
+
35
+ executor.without_default_logging do
36
+ yield
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+
5
+ # Write contents to a file on the given set of targets.
6
+ #
7
+ # > **Note:** Not available in apply block
8
+ Puppet::Functions.create_function(:write_file) do
9
+ # @param content File content to write.
10
+ # @param destination An absolute path on the target(s).
11
+ # @param targets A pattern identifying zero or more targets. See {get_targets} for accepted patterns.
12
+ # @param options A hash of additional options.
13
+ # @option options [Boolean] _catch_errors Whether to catch raised errors.
14
+ # @option options [String] _run_as User to run as using privilege escalation.
15
+ # @return A list of results, one entry per target.
16
+ # @example Write a file to a target
17
+ # $content = 'Hello, world!'
18
+ # write_file($content, '/Users/me/hello.txt', $targets)
19
+ dispatch :write_file do
20
+ required_param 'String', :content
21
+ required_param 'String[1]', :destination
22
+ required_param 'Boltlib::TargetSpec', :targets
23
+ optional_param 'Hash[String[1], Any]', :options
24
+ return_type 'ResultSet'
25
+ end
26
+
27
+ def write_file(content, destination, target_spec, options = {})
28
+ unless Puppet[:tasks]
29
+ raise Puppet::ParseErrorWithIssue
30
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING,
31
+ action: 'write_file')
32
+ end
33
+
34
+ executor = Puppet.lookup(:bolt_executor)
35
+ # Send Analytics Report
36
+ executor.report_function_call(self.class.name)
37
+
38
+ inventory = Puppet.lookup(:bolt_inventory)
39
+ targets = inventory.get_targets(target_spec)
40
+
41
+ executor.log_action("write file #{destination}", targets) do
42
+ executor.without_default_logging do
43
+ Tempfile.create do |tmp|
44
+ call_function('file::write', tmp.path, content)
45
+ call_function('upload_file', tmp.path, destination, targets, options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ # A PlanResult describes the supported return values of a plan. It
2
+ # should be used as the return type of functions that run plans and return the
3
+ # results.
4
+
5
+ type Boltlib::PlanResult = Variant[Boolean,
6
+ Numeric,
7
+ String,
8
+ Undef,
9
+ Error,
10
+ Result,
11
+ ApplyResult,
12
+ ResultSet,
13
+ Target,
14
+ ResourceInstance,
15
+ ContainerResult,
16
+ Future,
17
+ Array[Boltlib::PlanResult],
18
+ Hash[String, Boltlib::PlanResult]]
@@ -0,0 +1,7 @@
1
+ # A TargetSpec represents any String, Target or combination thereof that can be
2
+ # passed to get_targets() to return an Array[Target]. Generally, users
3
+ # shouldn't need to worry about the distinction between TargetSpec and
4
+ # Target/Array[Target], since the run_* functions will all handle them both
5
+ # automatically. But for use cases that need to deal with the exact list of
6
+ # Targets that will be used, get_targets() will return that.
7
+ type Boltlib::TargetSpec = Variant[String[1], Target, Array[Boltlib::TargetSpec]]
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Repeat the block until it returns a truthy value. Returns the value.
4
+ Puppet::Functions.create_function(:'ctrl::do_until') do
5
+ # @param options A hash of additional options.
6
+ # @param block The code block to repeat.
7
+ # @option options [Numeric] limit The number of times to repeat the block.
8
+ # @option options [Numeric] interval The number of seconds to wait before repeating the block.
9
+ # @return The value of the code block's last iteration
10
+ # @example Run a task until it succeeds
11
+ # ctrl::do_until() || {
12
+ # run_task('test', $target, '_catch_errors' => true).ok()
13
+ # }
14
+ # @example Run a task until it succeeds or fails 10 times
15
+ # ctrl::do_until('limit' => 10) || {
16
+ # run_task('test', $target, '_catch_errors' => true).ok()
17
+ # }
18
+ # @example Run a task and wait 10 seconds before running it again
19
+ # ctrl::do_until('interval' => 10) || {
20
+ # run_task('test', $target, '_catch_errors' => true).ok()
21
+ # }
22
+ dispatch :do_until do
23
+ optional_param 'Hash[String[1], Any]', :options
24
+ block_param
25
+ end
26
+
27
+ def do_until(options = {})
28
+ # Send Analytics Report
29
+ Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
30
+
31
+ limit = options['limit'] || 0
32
+ interval = options['interval']
33
+
34
+ i = 0
35
+ until (x = yield)
36
+ i += 1
37
+ break if limit != 0 && i >= limit
38
+ Kernel.sleep(interval) if interval
39
+ end
40
+ x
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Sleeps for specified number of seconds.
4
+ Puppet::Functions.create_function(:'ctrl::sleep') do
5
+ # @param period Time to sleep (in seconds)
6
+ # @example Sleep for 5 seconds
7
+ # ctrl::sleep(5)
8
+ dispatch :sleeper do
9
+ required_param 'Numeric', :period
10
+ return_type 'Undef'
11
+ end
12
+
13
+ def sleeper(period)
14
+ # Send Analytics Report
15
+ Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
16
+
17
+ sleep(period)
18
+ nil
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ # Returns an array containing all of the filenames except for "." and ".." in the given directory.
6
+ Puppet::Functions.create_function(:'dir::children', Puppet::Functions::InternalFunction) do
7
+ # @param dirname Absolute path or Puppet module name.
8
+ # @return Array of files in the given directory.
9
+ # @example List filenames from an absolute path.
10
+ # dir::children('/home/user/subdir/')
11
+ # @example List filenames from a Puppet file path.
12
+ # dir::children('puppet_agent')
13
+ dispatch :children do
14
+ scope_param
15
+ required_param 'String', :dirname
16
+ return_type 'Array'
17
+ end
18
+
19
+ def children(scope, dirname)
20
+ # Send Analytics Report
21
+ Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
22
+ modname, subpath = dirname.split(File::SEPARATOR, 2)
23
+ mod_path = scope.compiler.environment.module(modname)&.path
24
+
25
+ full_mod_path = File.join(mod_path, subpath || '') if mod_path
26
+
27
+ # Expand relative to the project directory if path is relative
28
+ project = Puppet.lookup(:bolt_project)
29
+ pathname = Pathname.new(dirname)
30
+ full_dir = pathname.absolute? ? dirname : File.expand_path(File.join(project.path, dirname))
31
+
32
+ # Sort for testability
33
+ Dir.children(full_mod_path || full_dir).sort
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Delete a file on localhost using ruby's `File.delete`. This will only delete
4
+ # files on the machine you run Bolt on.
5
+ Puppet::Functions.create_function(:'file::delete') do
6
+ # @param filename Absolute path.
7
+ # @example Delete a file from disk
8
+ # file::delete('C:/Users/me/report')
9
+ dispatch :delete do
10
+ required_param 'String[1]', :filename
11
+ return_type 'Undef'
12
+ end
13
+
14
+ def delete(filename)
15
+ # Send Analytics Report
16
+ Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
17
+
18
+ File.delete(filename)
19
+ nil
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Check if a local file exists using Puppet's
4
+ # `Puppet::Parser::Files.find_file()` function. This will only check files that
5
+ # are on the machine Bolt is run on.
6
+ Puppet::Functions.create_function(:'file::exists', Puppet::Functions::InternalFunction) do
7
+ # @param filename Absolute path or Puppet file path.
8
+ # @return Whether the file exists.
9
+ # @example Check a file on disk
10
+ # file::exists('/tmp/i_dumped_this_here')
11
+ # @example check a file from the modulepath
12
+ # file::exists('example/VERSION')
13
+ dispatch :exists do
14
+ scope_param
15
+ required_param 'String[1]', :filename
16
+ return_type 'Boolean'
17
+ end
18
+
19
+ def exists(scope, filename)
20
+ # Send Analytics Report
21
+ executor = Puppet.lookup(:bolt_executor) {}
22
+ executor&.report_function_call(self.class.name)
23
+
24
+ # Find the file path if it exists, otherwise return nil
25
+ found = Bolt::Util.find_file_from_scope(filename, scope)
26
+ found ? Puppet::FileSystem.exist?(found) : false
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Join file paths using ruby's `File.join()` function.
4
+ Puppet::Functions.create_function(:'file::join') do
5
+ # @param paths The paths to join.
6
+ # @return The joined file path.
7
+ # @example Join file paths
8
+ # file::join('./path', 'to/files')
9
+ dispatch :join do
10
+ required_repeated_param 'String', :paths
11
+ return_type 'String'
12
+ end
13
+
14
+ def join(*paths)
15
+ # Send Analytics Report
16
+ Puppet.lookup(:bolt_executor) {}&.report_function_call(self.class.name)
17
+
18
+ File.join(paths)
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Read a file on localhost and return its contents using ruby's `File.read`. This will
4
+ # only read files on the machine you run Bolt on.
5
+ Puppet::Functions.create_function(:'file::read', Puppet::Functions::InternalFunction) do
6
+ # @param filename Absolute path or Puppet file path.
7
+ # @return The file's contents.
8
+ # @example Read a file from disk
9
+ # file::read('/tmp/i_dumped_this_here')
10
+ # @example Read a file from the modulepath
11
+ # file::read('example/VERSION')
12
+ dispatch :read do
13
+ scope_param
14
+ required_param 'String[1]', :filename
15
+ return_type 'String'
16
+ end
17
+
18
+ def read(scope, filename)
19
+ # Send Analytics Report
20
+ executor = Puppet.lookup(:bolt_executor) {}
21
+ executor&.report_function_call(self.class.name)
22
+
23
+ # Find the file path if it exists, otherwise return nil
24
+ found = Bolt::Util.find_file_from_scope(filename, scope)
25
+ unless found && Puppet::FileSystem.exist?(found)
26
+ raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
27
+ Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: filename
28
+ )
29
+ end
30
+ executor&.report_file_source(self.class.name, filename)
31
+ File.read(found)
32
+ end
33
+ end