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,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bolt_spec/plans/mock_executor'
4
+ require 'bolt/config'
5
+ require 'bolt/inventory'
6
+ require 'bolt/pal'
7
+ require 'bolt/plugin'
8
+
9
+ # This helper is used to create the Bolt context necessary to load Bolt plan
10
+ # datatypes and functions. It accomplishes this by replacing bolt's executor
11
+ # with a mock executor. The mock executor allows calls to run_* functions to be
12
+ # stubbed out for testing. By default this executor will fail on any run_* call
13
+ # but stubs can be set up with allow_* and expect_* functions.
14
+ #
15
+ # Stub matching
16
+ #
17
+ # Stubs match invocations of run_* functions by default matching any call but
18
+ # with_targets and with_params helpers can further restrict the stub to match
19
+ # more exact invocations. It's possible a call to run_* could match multiple
20
+ # stubs. In this case the mock executor will first check for stubs specifically
21
+ # matching the task being run after which it will use the last stub that
22
+ # matched
23
+ #
24
+ #
25
+ # allow vs expect
26
+ #
27
+ # Stubs have two general modes bases on whether the test is making assertions
28
+ # on whether function was called. Allow stubs allow the run_* invocation to
29
+ # be called any number of times while expect stubs will fail if no run_*
30
+ # invocation matches them. The be_called_times(n) stub method can be used to
31
+ # ensure an allow stub is not called more than n times or that an expect stub
32
+ # is called exactly n times.
33
+ #
34
+ # Configuration
35
+ #
36
+ # By default the plan helpers use the modulepath set up for rspec-puppet and
37
+ # an otherwise empty bolt config and inventory. To create your own values for
38
+ # these override the modulepath, config, or inventory methods.
39
+ #
40
+ # Stubs:
41
+ # - allow_command(cmd), expect_command(cmd): expect the exact command
42
+ # - allow_script(script), expect_script(script): expect the script as <module>/path/to/file or an absolute path
43
+ # - allow_task(task), expect_task(task): expect the named task
44
+ # - allow_download(file), expect_download(file): expect the identified source file
45
+ # - allow_upload(file), expect_upload(file): expect the source file as <module>/path/to/file or an absolute path
46
+ # - allow_out_message, expect_out_message: expect a message to be passed to out::message (only modifiers are
47
+ # be_called_times(n), with_params(params), and not_be_called)
48
+ #
49
+ # Files with absolute path (for upload and script) must exist or those functions will fail.
50
+ #
51
+ # Stub modifiers:
52
+ # - be_called_times(n): if allowed, fail if the action is called more than 'n' times
53
+ # if expected, fail unless the action is called 'n' times
54
+ # - not_be_called: fail if the action is called
55
+ # - with_targets(targets): target or list of targets that you expect to be passed to the action
56
+ # - with_params(params): list of params and metaparams (or options) that you expect to be passed to the action.
57
+ # Corresponds to the action's last argument.
58
+ # - with_destination(dest): for upload_file and download_file, the expected destination path
59
+ # - always_return(value): return a Bolt::ResultSet of Bolt::Result objects with the specified value Hash
60
+ # command and script: only accept 'stdout' and 'stderr' keys
61
+ # upload: does not support this modifier
62
+ # download: does not support this modifier
63
+ # - return_for_targets(targets_to_values): return a Bolt::ResultSet of Bolt::Result objects from the Hash mapping
64
+ # targets to their value Hashes
65
+ # command and script: only accept 'stdout' and 'stderr' keys
66
+ # upload: does not support this modifier
67
+ # download: does not support this modifier
68
+ # - return(&block): invoke the block to construct a Bolt::ResultSet. The blocks parameters differ based on action
69
+ # command: `{ |targets:, command:, params:| ... }`
70
+ # script: `{ |targets:, script:, params:| ... }`
71
+ # task: `{ |targets:, task:, params:| ... }`
72
+ # upload: `{ |targets:, source:, destination:, params:| ... }`
73
+ # download: `{ |targets:, source:, destination:, params:| ... }`
74
+ # - error_with(err): return a failing Bolt::ResultSet, with Bolt::Result objects with the identified err hash
75
+ #
76
+ # Example:
77
+ #
78
+ # describe "mymod::myfunction" do
79
+ # include BoltSpec::BoltContext
80
+ #
81
+ # around :each do |example|
82
+ # in_bolt_context do
83
+ # example.run
84
+ # end
85
+ # end
86
+ #
87
+ # it "bolt_context runs a Puppet function with Bolt datatypes" do
88
+ # expect_out_message.with_params("Loaded TargetSpec localhost")
89
+ # is_expected.to run.with_params('localhost').and_return('localhost')
90
+ # end
91
+ # end
92
+
93
+ module BoltSpec
94
+ module BoltContext
95
+ def setup
96
+ unless @loaded
97
+ # This is slow so don't do it until we have to
98
+ Bolt::PAL.load_puppet
99
+ @loaded = true
100
+ end
101
+ end
102
+
103
+ def in_bolt_context(&block)
104
+ setup
105
+ old_modpath = RSpec.configuration.module_path
106
+ old_tasks = Puppet[:tasks]
107
+
108
+ # Set the things
109
+ Puppet[:tasks] = true
110
+ RSpec.configuration.module_path = [modulepath, Bolt::Config::Modulepath::BOLTLIB_PATH].join(File::PATH_SEPARATOR)
111
+ opts = {
112
+ bolt_executor: executor,
113
+ bolt_inventory: inventory,
114
+ bolt_pdb_client: nil,
115
+ apply_executor: nil
116
+ }
117
+ Puppet.override(opts, &block)
118
+
119
+ # Unset the things
120
+ RSpec.configuration.module_path = old_modpath
121
+ Puppet[:tasks] = old_tasks
122
+ end
123
+
124
+ # Override in your tests if needed
125
+ def modulepath
126
+ [RSpec.configuration.module_path]
127
+ rescue NoMethodError
128
+ raise "RSpec.configuration.module_path not defined set up rspec puppet or define modulepath for this test"
129
+ end
130
+
131
+ def executor
132
+ @executor ||= BoltSpec::Plans::MockExecutor.new(modulepath)
133
+ end
134
+
135
+ # Overrides inventory for tests.
136
+ def inventory_data
137
+ {}
138
+ end
139
+
140
+ # Overrides configuration for tests.
141
+ def config_data
142
+ {}
143
+ end
144
+
145
+ def inventory
146
+ @inventory ||= Bolt::Inventory.create_version(inventory_data, config.transport, config.transports, plugins)
147
+ end
148
+
149
+ # Override in your tests
150
+ def config
151
+ @config ||= begin
152
+ conf = Bolt::Config.new(Bolt::Project.default_project, config_data)
153
+ conf.modulepath = [modulepath].flatten
154
+ conf
155
+ end
156
+ end
157
+
158
+ def plugins
159
+ @plugins ||= Bolt::Plugin.new(config, pal)
160
+ end
161
+
162
+ def pal
163
+ @pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
164
+ config.hiera_config,
165
+ config.project.resource_types)
166
+ end
167
+
168
+ BoltSpec::Plans::MOCKED_ACTIONS.each do |action|
169
+ # Allowed action stubs can be called up to be_called_times number of times
170
+ define_method :"allow_#{action}" do |object|
171
+ executor.send(:"stub_#{action}", object).add_stub(inventory)
172
+ end
173
+
174
+ # Expected action stubs must be called exactly the expected number of times
175
+ # or at least once without be_called_times
176
+ define_method :"expect_#{action}" do |object|
177
+ send(:"allow_#{action}", object).expect_call
178
+ end
179
+
180
+ # This stub will catch any action call if there are no stubs specifically for that task
181
+ define_method :"allow_any_#{action}" do
182
+ executor.send(:"stub_#{action}", :default).add_stub(inventory)
183
+ end
184
+ end
185
+
186
+ # Does this belong here?
187
+ def allow_out_message
188
+ executor.stub_out_message.add_stub
189
+ end
190
+ alias allow_any_out_message allow_out_message
191
+
192
+ def expect_out_message
193
+ allow_out_message.expect_call
194
+ end
195
+
196
+ def allow_out_verbose
197
+ executor.stub_out_verbose.add_stub
198
+ end
199
+ alias allow_any_out_verbose allow_out_verbose
200
+
201
+ def expect_out_verbose
202
+ allow_out_verbose.expect_call
203
+ end
204
+
205
+ # Example helpers to mock other run functions
206
+ # The with_targets method makes sense for all stubs
207
+ # with_params could be reused for options
208
+ # They probably need special stub methods for other arguments through
209
+
210
+ # Scripts can be mocked like tasks by their name
211
+ # arguments is an array instead of a hash though
212
+ # so it probably should be set separately
213
+ # def allow_script(script_name)
214
+ #
215
+ # file uploads and downloads have a single destination and no arguments
216
+ # def allow_upload(source_name)
217
+ # def allow_download(source_name)
218
+ #
219
+ # Most of the information in commands is in the command string itself
220
+ # we may need more flexible allows than just the name/command string
221
+ # Only option params exist on a command.
222
+ # def allow_command(command)
223
+ # def allow_command_matching(command_regex)
224
+ # def allow_command(&block)
225
+ end
226
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class CommandStub < ActionStub
6
+ def matches(targets, _command, options)
7
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets.map(&:name))
8
+ return false
9
+ end
10
+
11
+ if @invocation[:options] && options != @invocation[:options]
12
+ return false
13
+ end
14
+
15
+ true
16
+ end
17
+
18
+ def call(targets, command, options)
19
+ @calls += 1
20
+ if @return_block
21
+ check_resultset(@return_block.call(targets: targets, command: command, params: options), command)
22
+ else
23
+ Bolt::ResultSet.new(targets.map { |target| @data[target.name] || default_for(target) })
24
+ end
25
+ end
26
+
27
+ def parameters
28
+ @invocation[:options]
29
+ end
30
+
31
+ def result_for(target, stdout: '', stderr: '')
32
+ value = {
33
+ 'stdout' => stdout,
34
+ 'stderr' => stderr,
35
+ 'merged_output' => "#{stdout}\n#{stderr}".strip,
36
+ 'exit_code' => 0
37
+ }
38
+
39
+ Bolt::Result.for_command(target, value, 'command', '', [])
40
+ end
41
+
42
+ # Public methods
43
+
44
+ def with_params(params)
45
+ @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
46
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
47
+ self
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class DownloadStub < ActionStub
6
+ def matches(targets, _source, destination, options)
7
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets.map(&:name))
8
+ return false
9
+ end
10
+
11
+ if @invocation[:destination] && destination != @invocation[:destination]
12
+ return false
13
+ end
14
+
15
+ if @invocation[:options] && options != @invocation[:options]
16
+ return false
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def call(targets, source, destination, options)
23
+ @calls += 1
24
+ if @return_block
25
+ results = @return_block.call(targets: targets, source: source, destination: destination, params: options)
26
+ check_resultset(results, source)
27
+ else
28
+ results = targets.map do |target|
29
+ if @data[:default].is_a?(Bolt::Error)
30
+ default_for(target)
31
+ else
32
+ download = File.join(destination, Bolt::Util.windows_basename(source))
33
+ Bolt::Result.for_download(target, source, destination, download)
34
+ end
35
+ end
36
+ Bolt::ResultSet.new(results)
37
+ end
38
+ end
39
+
40
+ def parameters
41
+ @invocation[:options]
42
+ end
43
+
44
+ def result_for(_target, **_data)
45
+ raise 'Download result cannot be changed'
46
+ end
47
+
48
+ # Public methods
49
+
50
+ def always_return(_data)
51
+ raise 'Download result cannot be changed'
52
+ end
53
+
54
+ def with_destination(destination)
55
+ @invocation[:destination] = destination
56
+ self
57
+ end
58
+
59
+ def with_params(params)
60
+ @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
61
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
62
+ self
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class PlanStub < ActionStub
6
+ def matches(_scope, _plan, params)
7
+ targets = params.fetch('nodes', params.fetch('targets', nil))
8
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets)
9
+ return false
10
+ end
11
+
12
+ if @invocation[:params] && params != @invocation[:params]
13
+ return false
14
+ end
15
+
16
+ true
17
+ end
18
+
19
+ def call(_scope, plan, params)
20
+ @calls += 1
21
+ if @return_block
22
+ check_plan_result(@return_block.call(plan: plan, params: params), plan)
23
+ else
24
+ default_for(nil)
25
+ end
26
+ end
27
+
28
+ def parameters
29
+ @invocation[:params]
30
+ end
31
+
32
+ # Allow any data.
33
+ def result_for(_target, **data)
34
+ Bolt::PlanResult.new(Bolt::Util.walk_keys(data, &:to_s), 'success')
35
+ end
36
+
37
+ # Public methods
38
+
39
+ # Restricts the stub to only match invocations with certain parameters.
40
+ # All parameters must match exactly.
41
+ def with_params(params)
42
+ @invocation[:params] = params
43
+ self
44
+ end
45
+
46
+ def return_for_targets(_data)
47
+ raise "return_for_targets is not implemented for plan spec tests (allow_plan, expect_plan, allow_any_plan, etc)"
48
+ end
49
+
50
+ def error_with(data, clazz = Bolt::PlanFailure)
51
+ super(data, clazz)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class ScriptStub < ActionStub
6
+ def matches(targets, _script, arguments, options)
7
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets.map(&:name))
8
+ return false
9
+ end
10
+
11
+ if @invocation[:arguments] && arguments != @invocation[:arguments]
12
+ return false
13
+ end
14
+
15
+ if @invocation[:options] && options != @invocation[:options]
16
+ return false
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def call(targets, script, arguments, options)
23
+ @calls += 1
24
+ if @return_block
25
+ # Merge arguments and options into params to match puppet function signature.
26
+ params = options.merge('arguments' => arguments)
27
+ check_resultset(@return_block.call(targets: targets, script: script, params: params), script)
28
+ else
29
+ Bolt::ResultSet.new(targets.map { |target| @data[target.name] || default_for(target) })
30
+ end
31
+ end
32
+
33
+ def parameters
34
+ @invocation[:params]
35
+ end
36
+
37
+ def result_for(target, stdout: '', stderr: '')
38
+ value = {
39
+ 'stdout' => stdout,
40
+ 'stderr' => stderr,
41
+ 'merged_output' => "#{stdout}\n#{stderr}".strip,
42
+ 'exit_code' => 0
43
+ }
44
+
45
+ Bolt::Result.for_command(target, value, 'script', '', [])
46
+ end
47
+
48
+ # Public methods
49
+
50
+ def with_params(params)
51
+ @invocation[:params] = params
52
+ @invocation[:arguments] = params['arguments']
53
+ @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
54
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
55
+ self
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class TaskStub < ActionStub
6
+ def matches(targets, _task, arguments, options)
7
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets.map(&:name))
8
+ return false
9
+ end
10
+
11
+ if @invocation[:arguments] && arguments != @invocation[:arguments]
12
+ return false
13
+ end
14
+
15
+ if @invocation[:options] && options != @invocation[:options]
16
+ return false
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def call(targets, task, arguments, options)
23
+ @calls += 1
24
+ if @return_block
25
+ # Merge arguments and options into params to match puppet function signature.
26
+ params = options.transform_keys { |k| "_#{k}" }
27
+ params = params.merge(arguments)
28
+
29
+ check_resultset(@return_block.call(targets: targets, task: task, params: params), task)
30
+ else
31
+ Bolt::ResultSet.new(targets.map { |target| @data[target.name] || default_for(target) })
32
+ end
33
+ end
34
+
35
+ def parameters
36
+ @invocation[:params]
37
+ end
38
+
39
+ # Allow any data.
40
+ def result_for(target, **data)
41
+ Bolt::Result.new(target, value: Bolt::Util.walk_keys(data, &:to_s))
42
+ end
43
+
44
+ # Public methods
45
+
46
+ # Restricts the stub to only match invocations with certain parameters.
47
+ # All parameters must match exactly.
48
+ def with_params(params)
49
+ @invocation[:params] = params
50
+ @invocation[:arguments] = params.reject { |k, _v| k.start_with?('_') }
51
+ @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
52
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
53
+ self
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BoltSpec
4
+ module Plans
5
+ class UploadStub < ActionStub
6
+ def matches(targets, _source, destination, options)
7
+ if @invocation[:targets] && Set.new(@invocation[:targets]) != Set.new(targets.map(&:name))
8
+ return false
9
+ end
10
+
11
+ if @invocation[:destination] && destination != @invocation[:destination]
12
+ return false
13
+ end
14
+
15
+ if @invocation[:options] && options != @invocation[:options]
16
+ return false
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def call(targets, source, destination, options)
23
+ @calls += 1
24
+ if @return_block
25
+ results = @return_block.call(targets: targets, source: source, destination: destination, params: options)
26
+ check_resultset(results, source)
27
+ else
28
+ results = targets.map do |target|
29
+ if @data[:default].is_a?(Bolt::Error)
30
+ default_for(target)
31
+ else
32
+ Bolt::Result.for_upload(target, source, destination)
33
+ end
34
+ end
35
+ Bolt::ResultSet.new(results)
36
+ end
37
+ end
38
+
39
+ def parameters
40
+ @invocation[:options]
41
+ end
42
+
43
+ def result_for(_target, **_data)
44
+ raise 'Upload result cannot be changed'
45
+ end
46
+
47
+ # Public methods
48
+
49
+ def always_return(_data)
50
+ raise 'Upload result cannot be changed'
51
+ end
52
+
53
+ def with_destination(destination)
54
+ @invocation[:destination] = destination
55
+ self
56
+ end
57
+
58
+ def with_params(params)
59
+ @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
60
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
61
+ self
62
+ end
63
+ end
64
+ end
65
+ end