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,63 @@
1
+ #! /opt/puppetlabs/puppet/bin/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require 'puppet'
6
+ require 'puppet/module_tool/tar'
7
+ require 'tempfile'
8
+
9
+ args = JSON.parse($stdin.read)
10
+
11
+ Dir.mktmpdir do |puppet_root|
12
+ # Create temporary directories for all core Puppet settings so we don't clobber
13
+ # existing state or read from puppet.conf. Also create a temporary modulepath.
14
+ moduledir = File.join(puppet_root, 'modules')
15
+ Dir.mkdir(moduledir)
16
+ cli = Puppet::Settings::REQUIRED_APP_SETTINGS.flat_map do |setting|
17
+ ["--#{setting}", File.join(puppet_root, setting.to_s.chomp('dir'))]
18
+ end
19
+ cli << '--modulepath' << moduledir
20
+ Puppet.initialize_settings(cli)
21
+
22
+ Tempfile.open('plugins.tar.gz') do |plugins|
23
+ File.binwrite(plugins, Base64.decode64(args['plugins']))
24
+ user = Etc.getpwuid.nil? ? Etc.getlogin : Etc.getpwuid.name
25
+ Puppet::ModuleTool::Tar.instance.unpack(plugins, moduledir, user)
26
+ end
27
+
28
+ env = Puppet.lookup(:environments).get('production')
29
+ env.each_plugin_directory do |dir|
30
+ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
31
+ end
32
+
33
+ if (conn_info = args['_target'])
34
+ unless (type = conn_info['remote-transport'])
35
+ puts "Cannot collect facts for a remote target without knowing the remote-transport type."
36
+ exit 1
37
+ end
38
+
39
+ begin
40
+ require 'puppet/resource_api/transport'
41
+ rescue LoadError
42
+ msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\
43
+ "gem version 1.8.0 or greater is required on the proxy target"
44
+ puts msg
45
+ exit 1
46
+ end
47
+
48
+ # Transport.connect will modify this hash!
49
+ transport_conn_info = conn_info.transform_keys(&:to_sym)
50
+ transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
51
+ Puppet::ResourceApi::Transport.inject_device(type, transport)
52
+
53
+ Puppet[:facts_terminus] = :network_device
54
+ Puppet[:certname] = conn_info['name']
55
+ end
56
+
57
+ facts = Puppet::Node::Facts.indirection.find(SecureRandom.uuid, environment: env)
58
+
59
+ facts.name = facts.values['clientcert']
60
+ puts(facts.values.to_json)
61
+ end
62
+
63
+ exit 0
@@ -0,0 +1,75 @@
1
+ #! /opt/puppetlabs/puppet/bin/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require 'puppet'
6
+ require 'puppet/module_tool/tar'
7
+ require 'tempfile'
8
+
9
+ args = JSON.parse($stdin.read)
10
+
11
+ RESOURCE_INSTANCE = /^([^\[]+)\[([^\]]+)\]$/.freeze
12
+
13
+ def instance(type_name, resource_name)
14
+ resource = Puppet::Resource.indirection.find("#{type_name}/#{resource_name}")
15
+ stringify_resource(resource)
16
+ end
17
+
18
+ Dir.mktmpdir do |puppet_root|
19
+ # Create temporary directories for all core Puppet settings so we don't clobber
20
+ # existing state or read from puppet.conf. Also create a temporary modulepath.
21
+ moduledir = File.join(puppet_root, 'modules')
22
+ Dir.mkdir(moduledir)
23
+ cli = Puppet::Settings::REQUIRED_APP_SETTINGS.flat_map do |setting|
24
+ ["--#{setting}", File.join(puppet_root, setting.to_s.chomp('dir'))]
25
+ end
26
+ cli << '--modulepath' << moduledir
27
+ Puppet.initialize_settings(cli)
28
+
29
+ Tempfile.open('plugins.tar.gz') do |plugins|
30
+ File.binwrite(plugins, Base64.decode64(args['plugins']))
31
+ user = Etc.getpwuid.nil? ? Etc.getlogin : Etc.getpwuid.name
32
+ Puppet::ModuleTool::Tar.instance.unpack(plugins, moduledir, user)
33
+ end
34
+
35
+ env = Puppet.lookup(:environments).get('production')
36
+ env.each_plugin_directory do |dir|
37
+ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
38
+ end
39
+
40
+ if (conn_info = args['_target'])
41
+ unless (type = conn_info['remote-transport'])
42
+ puts "Cannot discover resources for a remote target without knowing it's the remote-transport type."
43
+ exit 1
44
+ end
45
+
46
+ begin
47
+ require 'puppet/resource_api/transport'
48
+ rescue LoadError
49
+ msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\
50
+ "gem version 1.8.0 or greater is required on the proxy target"
51
+ puts msg
52
+ exit 1
53
+ end
54
+
55
+ # Transport.connect will modify this hash!
56
+ transport_conn_info = conn_info.transform_keys(&:to_sym)
57
+
58
+ transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
59
+ Puppet::ResourceApi::Transport.inject_device(type, transport)
60
+
61
+ Puppet[:facts_terminus] = :network_device
62
+ Puppet[:certname] = conn_info['name']
63
+ end
64
+
65
+ resources = args['resources'].flat_map do |resource_desc|
66
+ if (match = RESOURCE_INSTANCE.match(resource_desc))
67
+ Puppet::Resource.indirection.find("#{match[1]}/#{match[2]}", environment: env)
68
+ else
69
+ Puppet::Resource.indirection.search(resource_desc, environment: env)
70
+ end
71
+ end
72
+ puts({ 'resources' => resources }.to_json)
73
+ end
74
+
75
+ exit 0
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Aggregates the key/value pairs in the results of a ResultSet into a hash
4
+ # mapping the keys to a hash of each distinct value and how many targets returned
5
+ # that value for the key.
6
+ Puppet::Functions.create_function(:'aggregate::count') do
7
+ dispatch :aggregate_count do
8
+ param 'ResultSet', :resultset
9
+ end
10
+
11
+ def aggregate_count(resultset)
12
+ resultset.each_with_object({}) do |result, agg|
13
+ result.value.each do |key, val|
14
+ agg[key] ||= {}
15
+ agg[key][val.to_s] ||= 0
16
+ agg[key][val.to_s] += 1
17
+ end
18
+ agg
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Aggregates the key/value pairs in the results of a ResultSet into a hash
4
+ # mapping the keys to a hash of each distinct value and the list of nodes
5
+ # returning that value for the key.
6
+ Puppet::Functions.create_function(:'aggregate::nodes') do
7
+ dispatch :aggregate_nodes do
8
+ param 'ResultSet', :resultset
9
+ end
10
+
11
+ def aggregate_nodes(resultset)
12
+ resultset.each_with_object({}) do |result, agg|
13
+ result.value.each do |key, val|
14
+ agg[key] ||= {}
15
+ agg[key][val.to_s] ||= []
16
+ agg[key][val.to_s] << result.target.name
17
+ end
18
+ agg
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Aggregates the key/value pairs in the results of a ResultSet into a hash
4
+ # mapping the keys to a hash of each distinct value and the list of targets
5
+ # returning that value for the key.
6
+ Puppet::Functions.create_function(:'aggregate::targets') do
7
+ dispatch :aggregate_targets do
8
+ param 'ResultSet', :resultset
9
+ end
10
+
11
+ def aggregate_targets(resultset)
12
+ resultset.each_with_object({}) do |result, agg|
13
+ result.value.each do |key, val|
14
+ agg[key] ||= {}
15
+ agg[key][val.to_s] ||= []
16
+ agg[key][val.to_s] << result.target.name
17
+ end
18
+ agg
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,56 @@
1
+ # @summary
2
+ # Run a task, command, or script on targets and aggregate the results as
3
+ # a count of targets for each value of a key.
4
+ #
5
+ # This plan accepts an action and a list of targets. The action can be the name
6
+ # of a task, a script, or a command to run. It will run the action on the
7
+ # targets and aggregate the key/value pairs in each Result into a hash, mapping
8
+ # the keys to a hash of each distinct value and how many targets returned that
9
+ # value for the key.
10
+ #
11
+ # @param command
12
+ # The command to run. Mutually exclusive with script and task.
13
+ # @param script
14
+ # The path to the script to run. Mutually exclusive with command and task.
15
+ # @param task
16
+ # The name of the task to run. Mutually exclusive with command and script.
17
+ # @param targets
18
+ # The list of targets to run the action on.
19
+ # @param params
20
+ # A hash of parameters and options to pass to the `run_*` function
21
+ # associated with the action (e.g. run_task).
22
+ plan aggregate::count(
23
+ Optional[String[0]] $task = undef,
24
+ Optional[String[0]] $command = undef,
25
+ Optional[String[0]] $script = undef,
26
+ TargetSpec $targets,
27
+ Hash[String, Data] $params = {}
28
+ ) {
29
+
30
+ # Validation
31
+ $type_count = [$task, $command, $script].reduce(0) |$acc, $v| {
32
+ if ($v) {
33
+ $acc + 1
34
+ } else {
35
+ $acc
36
+ }
37
+ }
38
+
39
+ if ($type_count == 0) {
40
+ fail_plan("Must specify a command, script, or task to run", 'aggregate/invalid-params')
41
+ }
42
+
43
+ if ($type_count > 1) {
44
+ fail_plan("Must specify only one command, script, or task to run", 'aggregate/invalid-params')
45
+ }
46
+
47
+ $res = if ($task) {
48
+ run_task($task, $targets, $params)
49
+ } elsif ($command) {
50
+ run_command($command, $targets, $params)
51
+ } elsif ($script) {
52
+ run_script($script, $targets, $params)
53
+ }
54
+
55
+ return aggregate::count($res)
56
+ }
@@ -0,0 +1,56 @@
1
+ # @summary
2
+ # Run a task, command, or script on targets and aggregate the results as
3
+ # the list of targets for each value of a key in the results.
4
+ #
5
+ # This plan accepts an action and a list of targets. The action can be the name
6
+ # of a task, a script, or a command to run. It will run the action on the
7
+ # targets and aggregate the key/value pairs in each Result into a hash, mapping
8
+ # the keys to a hash of each distinct value and a list of targets returning that
9
+ # value.
10
+ #
11
+ # @param command
12
+ # The command to run. Mutually exclusive with script and task.
13
+ # @param script
14
+ # The path to the script to run. Mutually exclusive with command and task.
15
+ # @param task
16
+ # The name of the task to run. Mutually exclusive with command and script.
17
+ # @param targets
18
+ # The list of targets to run the action on.
19
+ # @param params
20
+ # A hash of parameters and options to pass to the `run_*` function
21
+ # associated with the action (e.g. run_task).
22
+ plan aggregate::targets(
23
+ Optional[String[0]] $task = undef,
24
+ Optional[String[0]] $command = undef,
25
+ Optional[String[0]] $script = undef,
26
+ TargetSpec $targets,
27
+ Hash[String, Data] $params = {}
28
+ ) {
29
+
30
+ # Validation
31
+ $type_count = [$task, $command, $script].reduce(0) |$acc, $v| {
32
+ if ($v) {
33
+ $acc + 1
34
+ } else {
35
+ $acc
36
+ }
37
+ }
38
+
39
+ if ($type_count == 0) {
40
+ fail_plan("Must specify a command, script, or task to run", 'aggregate/invalid-params')
41
+ }
42
+
43
+ if ($type_count > 1) {
44
+ fail_plan("Must specify only one command, script, or task to run", 'aggregate/invalid-params')
45
+ }
46
+
47
+ $res = if ($task) {
48
+ run_task($task, $targets, $params)
49
+ } elsif ($command) {
50
+ run_command($command, $targets, $params)
51
+ } elsif ($script) {
52
+ run_script($script, $targets, $params)
53
+ }
54
+
55
+ return aggregate::targets($res)
56
+ }
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Merges two ResultSets into a new ResultSet
4
+ Puppet::Functions.create_function(:'canary::merge') do
5
+ dispatch :merge_results do
6
+ param 'ResultSet', :merger
7
+ param 'ResultSet', :mergee
8
+ end
9
+
10
+ def merge_results(merger, mergee)
11
+ Bolt::ResultSet.new(merger.results + mergee.results)
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Splits an array into two groups, where the 1st group is a randomly selected
4
+ # sample of the input (of the specified size) and the 2nd group is the remainder.
5
+ #
6
+ # This function takes 2 parameters:
7
+ # * The array to split (Array)
8
+ # * The number of items to sample from the array (Integer)
9
+ #
10
+ # Returns an array of [<sample>, <remainder>].
11
+ Puppet::Functions.create_function(:'canary::random_split') do
12
+ dispatch :rand do
13
+ param 'Array', :arr
14
+ param 'Integer', :size
15
+ end
16
+
17
+ def rand(arr, size)
18
+ canaries = arr.sample(size)
19
+ rest = arr.reject { |r| canaries.include?(r) }
20
+ [canaries, rest]
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Returns a ResultSet with canary/skipped-target errors for each Target provided.
4
+ #
5
+ # This function takes a single parameter:
6
+ # * List of targets (Array[Variant[Target,String]])
7
+ #
8
+ # Returns a ResultSet.
9
+ Puppet::Functions.create_function(:'canary::skip') do
10
+ dispatch :skip_result do
11
+ param 'Array[Variant[Target,String]]', :targets
12
+ end
13
+
14
+ def skip_result(targets)
15
+ results = targets.map do |target|
16
+ target = Bolt::Target.new(target) unless target.is_a? Bolt::Target
17
+ Bolt::Result.new(target, value: { '_error' => {
18
+ 'msg' => "Skipped #{target.name} because of a previous failure",
19
+ 'kind' => 'canary/skipped-target',
20
+ 'details' => {}
21
+ } })
22
+ end
23
+ Bolt::ResultSet.new(results)
24
+ end
25
+ end
@@ -0,0 +1,100 @@
1
+ # @summary
2
+ # Run a task, command or script on canary targets before running it on all targets.
3
+ #
4
+ # This plan accepts a action and a $targets parameter. The action can be the name
5
+ # of a task, a script or a command to run. It will run the action on a canary
6
+ # group of targets and only continue to the rest of the targets if it succeeds on
7
+ # all canaries. This returns a ResultSet object with a Result for every target.
8
+ # Any skipped targets will have a 'canary/skipped-target' error kind.
9
+ #
10
+ # @param task
11
+ # The name of the task to run. Mutually exclusive with command and script.
12
+ # @param command
13
+ # The command to run. Mutually exclusive with task and script.
14
+ # @param script
15
+ # The script to run. Mutually exclusive with task and command.
16
+ # @param targets
17
+ # The target to run on.
18
+ # @param params
19
+ # The parameters to use for the task.
20
+ # @param canary_size
21
+ # How many targets to use in the canary group.
22
+ #
23
+ # @return ResultSet a merged resultset from running the action on all targets
24
+ #
25
+ # @example Run a command
26
+ # run_plan(canary, command => 'whoami', targets => $mytargets)
27
+ #
28
+ plan canary(
29
+ Optional[String[0]] $task = undef,
30
+ Optional[String[0]] $command = undef,
31
+ Optional[String[0]] $script = undef,
32
+ TargetSpec $targets,
33
+ Hash[String, Data] $params = {},
34
+ Integer $canary_size = 1
35
+ ) {
36
+
37
+ # Validation
38
+ $type_count = [$task, $command, $script].reduce(0) |$acc, $v| {
39
+ if ($v) {
40
+ $acc + 1
41
+ } else {
42
+ $acc
43
+ }
44
+ }
45
+
46
+ if ($type_count == 0) {
47
+ fail_plan("Must specify a command, script, or task to run", 'canary/invalid-params')
48
+ }
49
+
50
+ if ($type_count > 1) {
51
+ fail_plan("Must specify only one command, script, or task to run", 'canary/invalid-params')
52
+ }
53
+
54
+ [$canaries, $rest] = canary::random_split(get_targets($targets), $canary_size)
55
+ $catch_params = $params + { '_catch_errors' => true }
56
+
57
+ if ($task) {
58
+ $action = 'run_task'
59
+ $object = $task
60
+ $canr = run_task($task, $canaries, $catch_params)
61
+ if ($canr.ok) {
62
+ $restr = run_task($task, $rest, $catch_params)
63
+ }
64
+ } elsif ($command) {
65
+ $action = 'run_command'
66
+ $object = $command
67
+ $canr = run_command($command, $canaries, $catch_params)
68
+ if ($canr.ok) {
69
+ $restr = run_command($command, $rest, $catch_params)
70
+ }
71
+ } elsif ($script) {
72
+ $action = 'run_script'
73
+ $object = $script
74
+ $canr = run_script($script, $canaries, $catch_params)
75
+ if ($canr.ok) {
76
+ $restr = run_script($script, $rest, $catch_params)
77
+ }
78
+ }
79
+
80
+ unless ($canr.ok) {
81
+ $restr = canary::skip($rest)
82
+ }
83
+
84
+ $merged_result = canary::merge($canr, $restr)
85
+
86
+ unless ($merged_result.ok) {
87
+ if ($canr.ok) {
88
+ $message = "Plan failed for ${merged_result.error_set.count} targets."
89
+ }
90
+ else {
91
+ $message = "${canr.error_set.count} canary target failures. ${restr.count} targets skipped."
92
+ }
93
+ $details = {'action' => $action,
94
+ 'object' => $object,
95
+ 'result_set' => $merged_result}
96
+ fail_plan($message, 'bolt/run-failure', $details)
97
+ }
98
+
99
+ return $merged_result
100
+ }
@@ -0,0 +1,94 @@
1
+ # @summary
2
+ # Tests that the provided Puppet Connect input data is complete, meaning that all consuming inventory targets are connectable.
3
+ # You should run this plan with the following command:
4
+ # PUPPET_CONNECT_INPUT_DATA=/path/to/input_data.yaml bolt plan run puppet_connect::test_input_data
5
+ # where /path/to/input_data.yaml is the path to the input_data.yaml file containing the key-value input for the
6
+ # puppet_connect_data plugin. If the plan fails on some targets, then you can use Bolt's --rerun option to rerun the plan on
7
+ # just the failed targets:
8
+ # PUPPET_CONNECT_INPUT_DATA=/path/to/input_data.yaml bolt plan run puppet_connect::test_input_data --rerun failure
9
+ # Note that this plan should only be used as part of the copy-pastable "test input data" workflow specified in the Puppet
10
+ # Connect docs.
11
+ #
12
+ # @param targets
13
+ # The set of targets to test. Usually this should be 'all', the default.
14
+ #
15
+ # @return ResultSet the result of invoking the 'is connectable?' query on all
16
+ # the targets. Note that this query currently consists of running the 'echo'
17
+ # command.
18
+ #
19
+ plan puppet_connect::test_input_data(TargetSpec $targets = 'all') {
20
+ $targs = get_targets($targets)
21
+ $unique_plugins = $targs.group_by |$t| {$t.plugin_hooks['puppet_library']}
22
+ if ($unique_plugins.keys.length > 1) {
23
+ out::message('Multiple puppet_library plugin hooks detected')
24
+ $unique_plugins.each |$plug, $target_list| {
25
+ $target_message = if ($target_list.length > 10) {
26
+ "${target_list.length} targets"
27
+ } else {
28
+ $target_list.join(', ')
29
+ }
30
+ out::message("Plugin hook ${plug} configured for ${target_message}")
31
+ }
32
+ fail_plan("The puppet_library plugin config must be the same across all targets")
33
+ }
34
+ $targs.each |$target| {
35
+ case $target.transport {
36
+ 'ssh': {
37
+ $private_key_config = dig($target.config, 'ssh', 'private-key')
38
+ if $private_key_config =~ String {
39
+ $msg = @("END")
40
+ The SSH private key of the ${$target} target points to a filepath on disk,
41
+ which is not allowed in Puppet Connect. Instead, the private key contents must
42
+ be specified and this should be done via the PuppetConnectData plugin. Below is
43
+ an example of a Puppet Connect-compatible specification of the private-key. First,
44
+ we start with the inventory file:
45
+ ...
46
+ private-key:
47
+ _plugin: puppet_connect_data
48
+ key: ssh_private_key
49
+ ...
50
+
51
+ Next is the corresponding entry in the input data file:
52
+ ...
53
+ ssh_private_key:
54
+ key-data:
55
+ <private_key_contents>
56
+ ...
57
+ | END
58
+
59
+ out::message($msg)
60
+ fail_plan("The SSH private key of the ${$target} target points to a filepath on disk")
61
+ }
62
+
63
+ # Disable SSH autoloading to prevent false positive results
64
+ # (input data is wrong but target is still connectable due
65
+ # to autoloaded config)
66
+ set_config($target, ['ssh', 'load-config'], false)
67
+ # Maintain configuration parity with Puppet Connect to improve
68
+ # the reliability of our test
69
+ set_config($target, ['ssh', 'host-key-check'], false)
70
+ }
71
+ 'winrm': {
72
+ # Maintain configuration parity with Puppet Connect
73
+ set_config($target, ['winrm', 'ssl'], false)
74
+ set_config($target, ['winrm', 'ssl-verify'], false)
75
+ }
76
+ default: {
77
+ fail_plan("Inventory contains target ${target} with unsupported transport, must be ssh or winrm")
78
+ }
79
+ }
80
+
81
+ # Bolt defaults to using the "module" based form of the puppet_agent plugin. Connect defaults
82
+ # to using the "task" based form as *only* the task based form in supported in Connect. This check
83
+ # ensures that if the default is not being used, only task based plugins are allowed.
84
+ $plugin = $target.plugin_hooks["puppet_library"]
85
+ $user_configured_plugin = $plugin != { "plugin"=> "puppet_agent", "stop_service"=> true }
86
+ if ($user_configured_plugin and $plugin["plugin"] != "task"){
87
+ fail_plan("Only task plugins are acceptable for puppet_library hook")
88
+ }
89
+ }
90
+ # The SSH/WinRM transports will report an 'unknown host' error for targets where
91
+ # 'host' is unknown so run_command's implementation will take care of raising that
92
+ # error for us.
93
+ return run_command('echo Connected', $targs)
94
+ }
@@ -0,0 +1,20 @@
1
+ # @summary
2
+ # Collect facts for the specified targets from PuppetDB and store them
3
+ # on the Targets.
4
+ #
5
+ # This plan accepts a list of targets to collect facts for from the configured
6
+ # PuppetDB connection. After collecting facts, they are stored on each target's
7
+ # Target object. The updated facts can then be accessed using `$target.facts`.
8
+ #
9
+ # @param targets
10
+ # The targets to collect facts for.
11
+ plan puppetdb_fact(TargetSpec $targets) {
12
+ $targs = get_targets($targets)
13
+ $certnames = $targs.map |$target| { $target.host }
14
+ $pdb_facts = puppetdb_fact($certnames)
15
+ $targs.each |$target| {
16
+ add_facts($target, $pdb_facts[$target.host])
17
+ }
18
+
19
+ return $pdb_facts
20
+ }