bolt 2.42.0 → 3.3.0

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

Potentially problematic release.


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

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +21 -19
  3. data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +25 -0
  5. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +6 -8
  6. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -2
  7. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +27 -5
  8. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
  9. data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +7 -3
  10. data/bolt-modules/file/lib/puppet/functions/file/read.rb +3 -2
  11. data/lib/bolt/analytics.rb +3 -2
  12. data/lib/bolt/applicator.rb +11 -1
  13. data/lib/bolt/apply_result.rb +1 -1
  14. data/lib/bolt/bolt_option_parser.rb +9 -116
  15. data/lib/bolt/catalog.rb +10 -29
  16. data/lib/bolt/cli.rb +90 -154
  17. data/lib/bolt/config.rb +66 -239
  18. data/lib/bolt/config/options.rb +79 -102
  19. data/lib/bolt/config/transport/local.rb +1 -0
  20. data/lib/bolt/config/transport/lxd.rb +21 -0
  21. data/lib/bolt/config/transport/options.rb +9 -2
  22. data/lib/bolt/config/transport/orch.rb +1 -0
  23. data/lib/bolt/executor.rb +23 -6
  24. data/lib/bolt/inventory.rb +1 -1
  25. data/lib/bolt/inventory/group.rb +7 -4
  26. data/lib/bolt/logger.rb +123 -11
  27. data/lib/bolt/module_installer.rb +6 -4
  28. data/lib/bolt/module_installer/puppetfile.rb +2 -2
  29. data/lib/bolt/module_installer/resolver.rb +59 -14
  30. data/lib/bolt/module_installer/specs/forge_spec.rb +10 -4
  31. data/lib/bolt/module_installer/specs/git_spec.rb +19 -4
  32. data/lib/bolt/outputter/human.rb +56 -17
  33. data/lib/bolt/outputter/json.rb +16 -16
  34. data/lib/bolt/outputter/rainbow.rb +3 -3
  35. data/lib/bolt/pal.rb +95 -15
  36. data/lib/bolt/pal/yaml_plan.rb +9 -4
  37. data/lib/bolt/pal/yaml_plan/evaluator.rb +5 -153
  38. data/lib/bolt/pal/yaml_plan/step.rb +91 -52
  39. data/lib/bolt/pal/yaml_plan/step/command.rb +16 -16
  40. data/lib/bolt/pal/yaml_plan/step/download.rb +15 -16
  41. data/lib/bolt/pal/yaml_plan/step/eval.rb +11 -11
  42. data/lib/bolt/pal/yaml_plan/step/message.rb +13 -4
  43. data/lib/bolt/pal/yaml_plan/step/plan.rb +19 -15
  44. data/lib/bolt/pal/yaml_plan/step/resources.rb +82 -21
  45. data/lib/bolt/pal/yaml_plan/step/script.rb +32 -17
  46. data/lib/bolt/pal/yaml_plan/step/task.rb +19 -16
  47. data/lib/bolt/pal/yaml_plan/step/upload.rb +16 -17
  48. data/lib/bolt/pal/yaml_plan/transpiler.rb +2 -1
  49. data/lib/bolt/plan_creator.rb +1 -1
  50. data/lib/bolt/plugin.rb +2 -2
  51. data/lib/bolt/plugin/cache.rb +7 -7
  52. data/lib/bolt/plugin/module.rb +0 -23
  53. data/lib/bolt/plugin/puppet_connect_data.rb +77 -0
  54. data/lib/bolt/plugin/puppetdb.rb +1 -1
  55. data/lib/bolt/project.rb +54 -81
  56. data/lib/bolt/project_manager.rb +5 -4
  57. data/lib/bolt/project_manager/module_migrator.rb +7 -6
  58. data/lib/bolt/rerun.rb +1 -1
  59. data/lib/bolt/result.rb +6 -1
  60. data/lib/bolt/shell.rb +16 -0
  61. data/lib/bolt/shell/bash.rb +57 -25
  62. data/lib/bolt/shell/bash/tmpdir.rb +6 -3
  63. data/lib/bolt/shell/powershell.rb +33 -10
  64. data/lib/bolt/shell/powershell/snippets.rb +37 -150
  65. data/lib/bolt/task.rb +2 -2
  66. data/lib/bolt/transport/base.rb +0 -9
  67. data/lib/bolt/transport/docker.rb +1 -125
  68. data/lib/bolt/transport/docker/connection.rb +86 -161
  69. data/lib/bolt/transport/local.rb +1 -9
  70. data/lib/bolt/transport/lxd.rb +26 -0
  71. data/lib/bolt/transport/lxd/connection.rb +99 -0
  72. data/lib/bolt/transport/orch/connection.rb +1 -1
  73. data/lib/bolt/transport/ssh.rb +1 -2
  74. data/lib/bolt/transport/ssh/connection.rb +2 -2
  75. data/lib/bolt/transport/winrm/connection.rb +1 -1
  76. data/lib/bolt/validator.rb +2 -2
  77. data/lib/bolt/version.rb +1 -1
  78. data/lib/bolt_server/config.rb +1 -1
  79. data/lib/bolt_server/transport_app.rb +61 -32
  80. data/lib/bolt_spec/bolt_context.rb +9 -4
  81. data/lib/bolt_spec/plans.rb +1 -109
  82. data/lib/bolt_spec/plans/action_stubs.rb +1 -1
  83. data/lib/bolt_spec/plans/mock_executor.rb +4 -0
  84. data/libexec/bolt_catalog +1 -1
  85. data/modules/aggregate/plans/count.pp +21 -0
  86. data/modules/aggregate/plans/targets.pp +21 -0
  87. data/modules/puppet_connect/plans/test_input_data.pp +67 -0
  88. data/modules/puppetdb_fact/plans/init.pp +10 -0
  89. metadata +13 -9
  90. data/modules/aggregate/plans/nodes.pp +0 -36
@@ -5,119 +5,11 @@ require 'bolt_spec/plans/mock_executor'
5
5
  require 'bolt/pal'
6
6
 
7
7
  # These helpers are intended to be used for plan unit testing without calling
8
- # out to target nodes. It uses the BoltContext helper to set up a mock executor
8
+ # out to targets. It uses the BoltContext helper to set up a mock executor
9
9
  # which allows calls to run_* functions to be stubbed for testing. The context
10
10
  # helper also loads Bolt datatypes and plan functions to be used by the code
11
11
  # being tested.
12
12
  #
13
- # Stub matching
14
- #
15
- # Stubs match invocations of run_* functions by default matching any call but
16
- # with_targets and with_params helpers can further restrict the stub to match
17
- # more exact invocations. It's possible a call to run_* could match multiple
18
- # stubs. In this case the mock executor will first check for stubs specifically
19
- # matching the task being run after which it will use the last stub that
20
- # matched
21
- #
22
- #
23
- # allow vs expect
24
- #
25
- # Stubs have two general modes bases on whether the test is making assertions
26
- # on whether function was called. Allow stubs allow the run_* invocation to
27
- # be called any number of times while expect stubs will fail if no run_*
28
- # invocation matches them. The be_called_times(n) stub method can be used to
29
- # ensure an allow stub is not called more than n times or that an expect stub
30
- # is called exactly n times.
31
- #
32
- # Configuration
33
- #
34
- # To configure Puppet and Bolt at the beginning of tests, add the following
35
- # line to your spec_helper.rb:
36
- #
37
- # BoltSpec::Plans.init
38
- #
39
- # By default the plan helpers use the modulepath set up for rspec-puppet and
40
- # an otherwise empty bolt config and inventory. To create your own values for
41
- # these override the modulepath, config, or inventory methods.
42
- #
43
- # Sub-plan Execution
44
- #
45
- # When testing a plan, often times those plans call other plans in order to
46
- # build complex workflows. To support this we offer running in two different
47
- # modes:
48
- # execute_any_plan (default) - This mode will execute any plan that is encountered
49
- # without having to be stubbed/mocked. This default mode allows for plan control
50
- # flow to behave as normal. If you choose to stub/mock out a sub-plan in this mode
51
- # that will be honored and the sub-plan will not be executed. We will use the modifiers
52
- # on the stub to check for the conditions specified (example: be_called_times(3))
53
- #
54
- # execute_no_plan - This mode will not execute a plans that it encounters. Instead, when
55
- # a plan is encountered it will throw an error unless the plan is mocked out. This
56
- # mode is useful for ensuring that there are no plans called that you do not expect.
57
- # This plan requires authors to mock out all sub-plans that may be invoked when running
58
- # tests.
59
- #
60
- # TODO:
61
- # - Allow description based stub matching
62
- # - Better testing of plan errors
63
- # - Better error collection around call counts. Show what stubs exists and more than a single failure
64
- # - Allow stubbing with a block(at the double level? As a matched stub?)
65
- # - package code so that it can be used for testing modules outside of this repo
66
- # - set subject from describe and provide matchers similar to rspec puppets function tests
67
- # - Allow specific plans to be executed when running in execute_no_plan mode.
68
- #
69
- # MAYBE TODO?:
70
- # - validate call expectations at the end of the example instead of in run_plan
71
- # - resultset matchers to help testing canary like plans?
72
- # - inventory matchers to help testing plans that change inventory
73
- #
74
- # Flags:
75
- # - execute_any_plan: execute any plan that is encountered unless it is mocked (default)
76
- # - execute_no_plan: throw an error if a plan is encountered that is not stubbed
77
- #
78
- # Stubs:
79
- # - allow_command(cmd), expect_command(cmd): expect the exact command
80
- # - allow_plan(plan), expect_plan(plan): expect the named plan
81
- # - allow_script(script), expect_script(script): expect the script as <module>/path/to/file
82
- # - allow_task(task), expect_task(task): expect the named task
83
- # - allow_download(file), expect_download(file): expect the identified source file
84
- # - allow_upload(file), expect_upload(file): expect the identified source file
85
- # - allow_apply_prep: allows `apply_prep` to be invoked in the plan but does not allow modifiers
86
- # - allow_apply: allows `apply` to be invoked in the plan but does not allow modifiers
87
- # - allow_out_message, expect_out_message: expect a message to be passed to out::message (only modifiers are
88
- # be_called_times(n), with_params(params), and not_be_called)
89
- #
90
- # Stub modifiers:
91
- # - be_called_times(n): if allowed, fail if the action is called more than 'n' times
92
- # if expected, fail unless the action is called 'n' times
93
- # - not_be_called: fail if the action is called
94
- # - with_targets(targets): target or list of targets that you expect to be passed to the action
95
- # plan: does not support this modifier
96
- # - with_params(params): list of params and metaparams (or options) that you expect to be passed to the action.
97
- # Corresponds to the action's last argument.
98
- # - with_destination(dest): for upload_file and download_file, the expected destination path
99
- # - always_return(value): return a Bolt::ResultSet of Bolt::Result objects with the specified value Hash
100
- # plan: returns a Bolt::PlanResult with the specified value with a status of 'success'
101
- # command and script: only accept 'stdout' and 'stderr' keys
102
- # upload: does not support this modifier
103
- # download: does not support this modifier
104
- # - return_for_targets(targets_to_values): return a Bolt::ResultSet of Bolt::Result objects from the Hash mapping
105
- # targets to their value Hashes
106
- # command and script: only accept 'stdout' and 'stderr' keys
107
- # upload: does not support this modifier
108
- # download: does not support this modifier
109
- # plan: does not support this modifier
110
- # - return(&block): invoke the block to construct a Bolt::ResultSet. The blocks parameters differ based on action
111
- # command: `{ |targets:, command:, params:| ... }`
112
- # plan: `{ |plan:, params:| ... }`
113
- # script: `{ |targets:, script:, params:| ... }`
114
- # task: `{ |targets:, task:, params:| ... }`
115
- # upload: `{ |targets:, source:, destination:, params:| ... }`
116
- # download: `{ |targets:, source:, destination:, params:| ... }`
117
- # - error_with(err): return a failing Bolt::ResultSet, with Bolt::Result objects with the identified err hash
118
- # plans will throw a Bolt::PlanFailure that will be returned as the value of
119
- # the Bolt::PlanResult object with a status of 'failure'.
120
- #
121
13
  # Example:
122
14
  # describe "my_plan" do
123
15
  # it 'should return' do
@@ -177,7 +177,7 @@ module BoltSpec
177
177
  if data['msg'] && data['kind'] && (data.keys - %w[msg kind details issue_code]).empty?
178
178
  @data[:default] = clazz.new(data['msg'], data['kind'], data['details'], data['issue_code'])
179
179
  else
180
- $stderr.puts "In the future 'error_with()' may require msg and kind, and " \
180
+ $stderr.puts "In the future 'error_with()' might require msg and kind, and " \
181
181
  "optionally accept only details and issue_code."
182
182
  @data[:default] = data
183
183
  end
@@ -214,8 +214,12 @@ module BoltSpec
214
214
 
215
215
  def report_bundled_content(_mode, _name); end
216
216
 
217
+ def report_file_source(_plan_function, _source); end
218
+
217
219
  def report_apply(_statements, _resources); end
218
220
 
221
+ def report_yaml_plan(_plan); end
222
+
219
223
  def publish_event(event)
220
224
  if event[:type] == :message
221
225
  unless @stub_out_message
data/libexec/bolt_catalog CHANGED
@@ -56,7 +56,7 @@ when "compile"
56
56
  else
57
57
  e.message
58
58
  end
59
- puts({ message: message }.to_json)
59
+ puts({ message: message, backtrace: e.backtrace }.to_json)
60
60
  exit 1
61
61
  rescue StandardError => e
62
62
  puts({ message: e.message }.to_json)
@@ -1,3 +1,24 @@
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).
1
22
  plan aggregate::count(
2
23
  Optional[String[0]] $task = undef,
3
24
  Optional[String[0]] $command = undef,
@@ -1,3 +1,24 @@
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).
1
22
  plan aggregate::targets(
2
23
  Optional[String[0]] $task = undef,
3
24
  Optional[String[0]] $command = undef,
@@ -0,0 +1,67 @@
1
+ # @summary
2
+ # Tests that the provided Puppet Connect input data is complete, meaning that all consuming inventory targets are connectable.
3
+ #
4
+ # This plan should only be used as part of the copy-pastable "test input data"
5
+ # workflow specified in the Puppet Connect docs.
6
+ #
7
+ # @param targets
8
+ # The set of targets to test. Usually this should be 'all', the default.
9
+ #
10
+ # @return ResultSet the result of invoking the 'is connectable?' query on all
11
+ # the targets. Note that this query currently consists of running the 'echo'
12
+ # command.
13
+ #
14
+ plan puppet_connect::test_input_data(TargetSpec $targets = 'all') {
15
+ $targs = get_targets($targets)
16
+ $targs.each |$target| {
17
+ case $target.transport {
18
+ 'ssh': {
19
+ $private_key_config = dig($target.config, 'ssh', 'private-key')
20
+ if $private_key_config =~ String {
21
+ $msg = @("END")
22
+ The SSH private key of the ${$target} target points to a filepath on disk,
23
+ which is not allowed in Puppet Connect. Instead, the private key contents must
24
+ be specified and this should be done via the PuppetConnectData plugin. Below is
25
+ an example of a Puppet Connect-compatible specification of the private-key. First,
26
+ we start with the inventory file:
27
+ ...
28
+ private-key:
29
+ _plugin: puppet_connect_data
30
+ key: ssh_private_key
31
+ ...
32
+
33
+ Next is the corresponding entry in the input data file:
34
+ ...
35
+ ssh_private_key:
36
+ key-data:
37
+ <private_key_contents>
38
+ ...
39
+ | END
40
+
41
+ out::message($msg)
42
+ fail_plan("The SSH private key of the ${$target} target points to a filepath on disk")
43
+ }
44
+
45
+ # Disable SSH autoloading to prevent false positive results
46
+ # (input data is wrong but target is still connectable due
47
+ # to autoloaded config)
48
+ set_config($target, ['ssh', 'load-config'], false)
49
+ # Maintain configuration parity with Puppet Connect to improve
50
+ # the reliability of our test
51
+ set_config($target, ['ssh', 'host-key-check'], false)
52
+ }
53
+ 'winrm': {
54
+ # Maintain configuration parity with Puppet Connect
55
+ set_config($target, ['winrm', 'ssl'], false)
56
+ set_config($target, ['winrm', 'ssl-verify'], false)
57
+ }
58
+ default: {
59
+ fail_plan("Inventory contains target ${target} with unsupported transport, must be ssh or winrm")
60
+ }
61
+ }
62
+ }
63
+ # The SSH/WinRM transports will report an 'unknown host' error for targets where
64
+ # 'host' is unknown so run_command's implementation will take care of raising that
65
+ # error for us.
66
+ return run_command('echo Connected', $targs)
67
+ }
@@ -1,3 +1,13 @@
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.
1
11
  plan puppetdb_fact(TargetSpec $targets) {
2
12
  $targs = get_targets($targets)
3
13
  $certnames = $targs.map |$target| { $target.host }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.42.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-11 00:00:00.000000000 Z
11
+ date: 2021-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: '0.4'
187
+ version: '0.5'
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: '0.4'
194
+ version: '0.5'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: puppet
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -350,16 +350,16 @@ dependencies:
350
350
  name: puppetlabs_spec_helper
351
351
  requirement: !ruby/object:Gem::Requirement
352
352
  requirements:
353
- - - "~>"
353
+ - - "<="
354
354
  - !ruby/object:Gem::Version
355
- version: '2.7'
355
+ version: 2.15.0
356
356
  type: :development
357
357
  prerelease: false
358
358
  version_requirements: !ruby/object:Gem::Requirement
359
359
  requirements:
360
- - - "~>"
360
+ - - "<="
361
361
  - !ruby/object:Gem::Version
362
- version: '2.7'
362
+ version: 2.15.0
363
363
  - !ruby/object:Gem::Dependency
364
364
  name: rake
365
365
  requirement: !ruby/object:Gem::Requirement
@@ -467,6 +467,7 @@ files:
467
467
  - lib/bolt/config/transport/base.rb
468
468
  - lib/bolt/config/transport/docker.rb
469
469
  - lib/bolt/config/transport/local.rb
470
+ - lib/bolt/config/transport/lxd.rb
470
471
  - lib/bolt/config/transport/options.rb
471
472
  - lib/bolt/config/transport/orch.rb
472
473
  - lib/bolt/config/transport/remote.rb
@@ -523,6 +524,7 @@ files:
523
524
  - lib/bolt/plugin/env_var.rb
524
525
  - lib/bolt/plugin/module.rb
525
526
  - lib/bolt/plugin/prompt.rb
527
+ - lib/bolt/plugin/puppet_connect_data.rb
526
528
  - lib/bolt/plugin/puppetdb.rb
527
529
  - lib/bolt/plugin/task.rb
528
530
  - lib/bolt/project.rb
@@ -554,6 +556,8 @@ files:
554
556
  - lib/bolt/transport/docker/connection.rb
555
557
  - lib/bolt/transport/local.rb
556
558
  - lib/bolt/transport/local/connection.rb
559
+ - lib/bolt/transport/lxd.rb
560
+ - lib/bolt/transport/lxd/connection.rb
557
561
  - lib/bolt/transport/orch.rb
558
562
  - lib/bolt/transport/orch/connection.rb
559
563
  - lib/bolt/transport/remote.rb
@@ -608,12 +612,12 @@ files:
608
612
  - modules/aggregate/lib/puppet/functions/aggregate/nodes.rb
609
613
  - modules/aggregate/lib/puppet/functions/aggregate/targets.rb
610
614
  - modules/aggregate/plans/count.pp
611
- - modules/aggregate/plans/nodes.pp
612
615
  - modules/aggregate/plans/targets.pp
613
616
  - modules/canary/lib/puppet/functions/canary/merge.rb
614
617
  - modules/canary/lib/puppet/functions/canary/random_split.rb
615
618
  - modules/canary/lib/puppet/functions/canary/skip.rb
616
619
  - modules/canary/plans/init.pp
620
+ - modules/puppet_connect/plans/test_input_data.pp
617
621
  - modules/puppetdb_fact/plans/init.pp
618
622
  homepage: https://github.com/puppetlabs/bolt
619
623
  licenses:
@@ -1,36 +0,0 @@
1
- plan aggregate::nodes(
2
- Optional[String[0]] $task = undef,
3
- Optional[String[0]] $command = undef,
4
- Optional[String[0]] $script = undef,
5
- TargetSpec $nodes,
6
- Hash[String, Data] $params = {}
7
- ) {
8
-
9
- # Validation
10
- $type_count = [$task, $command, $script].reduce(0) |$acc, $v| {
11
- if ($v) {
12
- $acc + 1
13
- } else {
14
- $acc
15
- }
16
- }
17
-
18
- if ($type_count == 0) {
19
- fail_plan("Must specify a command, script, or task to run", 'aggregate/invalid-params')
20
- }
21
-
22
- if ($type_count > 1) {
23
- fail_plan("Must specify only one command, script, or task to run", 'aggregate/invalid-params')
24
- }
25
-
26
- $res = if ($task) {
27
- run_task($task, $nodes, $params)
28
- } elsif ($command) {
29
- run_command($command, $nodes, $params)
30
- } elsif ($script) {
31
- run_script($script, $nodes, $params)
32
- }
33
-
34
- return aggregate::nodes($res)
35
- }
36
-