bolt 3.7.0 → 3.9.1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +3 -3
  3. data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +26 -0
  4. data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +27 -0
  5. data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
  6. data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +43 -0
  7. data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +29 -0
  8. data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +34 -0
  9. data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +55 -0
  10. data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +1 -0
  11. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +10 -6
  12. data/bolt-modules/boltlib/lib/puppet/functions/background.rb +61 -0
  13. data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +5 -9
  14. data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +29 -13
  15. data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +1 -0
  16. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +5 -15
  17. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +10 -18
  18. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +8 -17
  19. data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +8 -15
  20. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +10 -18
  21. data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +91 -0
  22. data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +1 -0
  23. data/bolt-modules/boltlib/types/planresult.pp +1 -0
  24. data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +2 -0
  25. data/bolt-modules/file/lib/puppet/functions/file/exists.rb +9 -3
  26. data/bolt-modules/file/lib/puppet/functions/file/read.rb +6 -2
  27. data/bolt-modules/file/lib/puppet/functions/file/readable.rb +8 -3
  28. data/guides/guide.txt +17 -0
  29. data/guides/inventory.txt +5 -0
  30. data/guides/links.txt +13 -0
  31. data/guides/targets.txt +13 -15
  32. data/guides/transports.txt +23 -0
  33. data/lib/bolt/applicator.rb +4 -3
  34. data/lib/bolt/bolt_option_parser.rb +320 -212
  35. data/lib/bolt/catalog.rb +2 -1
  36. data/lib/bolt/cli.rb +66 -29
  37. data/lib/bolt/config/options.rb +2 -1
  38. data/lib/bolt/config/transport/docker.rb +5 -1
  39. data/lib/bolt/config/transport/lxd.rb +1 -1
  40. data/lib/bolt/config/transport/options.rb +2 -1
  41. data/lib/bolt/config/transport/podman.rb +5 -1
  42. data/lib/bolt/error.rb +11 -1
  43. data/lib/bolt/executor.rb +55 -72
  44. data/lib/bolt/fiber_executor.rb +141 -0
  45. data/lib/bolt/logger.rb +1 -1
  46. data/lib/bolt/module_installer/specs.rb +1 -1
  47. data/lib/bolt/module_installer/specs/git_spec.rb +10 -6
  48. data/lib/bolt/outputter/human.rb +10 -5
  49. data/lib/bolt/outputter/json.rb +4 -0
  50. data/lib/bolt/pal.rb +64 -3
  51. data/lib/bolt/plan_future.rb +66 -0
  52. data/lib/bolt/result.rb +5 -0
  53. data/lib/bolt/transport/docker/connection.rb +7 -4
  54. data/lib/bolt/transport/lxd/connection.rb +4 -0
  55. data/lib/bolt/transport/podman/connection.rb +4 -0
  56. data/lib/bolt/transport/ssh/connection.rb +3 -6
  57. data/lib/bolt/util.rb +73 -1
  58. data/lib/bolt/version.rb +1 -1
  59. data/lib/bolt_server/config.rb +1 -1
  60. data/lib/bolt_server/request_error.rb +11 -0
  61. data/lib/bolt_server/transport_app.rb +63 -95
  62. data/lib/bolt_spec/plans/mock_executor.rb +40 -45
  63. data/lib/bolt_spec/run.rb +4 -1
  64. data/modules/puppet_connect/plans/test_input_data.pp +8 -3
  65. metadata +11 -3
  66. data/lib/bolt/yarn.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 575cccb1487a82a6537a83d5d23a89d9e3ed44898af25e2fe34acda2ecd765ae
4
- data.tar.gz: a9de53717fdcb5380f95ef5ee1fb26b3d28eaa59f92355d9558954d14192f307
3
+ metadata.gz: 677d817ea21f24c36b06d830a6a4f60cc11a1c288b9bc948ad69ee47f59da4f9
4
+ data.tar.gz: a5045561603829eda876b5558082ecfa234916393ed4c92e6c5e7851c3cf1f2f
5
5
  SHA512:
6
- metadata.gz: 60378d6872763f5fb557deae88207c29db0626d90562e37d80df1f604368629049da79ff0a0216602057566c7eb10892855f33a99b03bfc348fce8b443e7682d
7
- data.tar.gz: e2f8dd460e346648e53921e299db5b7beaf4ba1a0cd7efe95728e2e2d42c3e4b3624c40ef8a94a21b7e4be5003d67a1a64c48d1a36a9e314c4d7bb296ce85eab
6
+ metadata.gz: 111b4df917e7788816f8ccbac0b1f7ed5ecb35af9ddec145aece1aa8ad8dd10c617383ce0b17b5e9146a528ad15e28751771eba0bef1fb08ddcd91c3db200c62
7
+ data.tar.gz: cea97329b768ee991b0757bd0a4ff7ae28b2f0a68b678989adaee488a4c98d2354c618bc4663be18482088e856307238e7e04ac823b3dd65a95465fc08ed8254
data/Puppetfile CHANGED
@@ -6,7 +6,7 @@ moduledir File.join(File.dirname(__FILE__), 'modules')
6
6
 
7
7
  # Core modules used by 'apply'
8
8
  mod 'puppetlabs-service', '2.0.0'
9
- mod 'puppetlabs-puppet_agent', '4.5.0'
9
+ mod 'puppetlabs-puppet_agent', '4.6.1'
10
10
  mod 'puppetlabs-facts', '1.4.0'
11
11
 
12
12
  # Core types and providers for Puppet 6
@@ -17,7 +17,7 @@ mod 'puppetlabs-sshkeys_core', '2.2.0'
17
17
  mod 'puppetlabs-zfs_core', '1.2.0'
18
18
  mod 'puppetlabs-cron_core', '1.0.5'
19
19
  mod 'puppetlabs-mount_core', '1.0.4'
20
- mod 'puppetlabs-selinux_core', '1.0.4'
20
+ mod 'puppetlabs-selinux_core', '1.1.0'
21
21
  mod 'puppetlabs-yumrepo_core', '1.0.7'
22
22
  mod 'puppetlabs-zone_core', '1.0.3'
23
23
 
@@ -29,7 +29,7 @@ mod 'puppetlabs-python_task_helper', '0.5.0'
29
29
  mod 'puppetlabs-reboot', '4.0.2'
30
30
  mod 'puppetlabs-ruby_task_helper', '0.6.0'
31
31
  mod 'puppetlabs-ruby_plugin_helper', '0.2.0'
32
- mod 'puppetlabs-stdlib', '7.0.0'
32
+ mod 'puppetlabs-stdlib', '7.0.1'
33
33
 
34
34
  # Plugin modules
35
35
  mod 'puppetlabs-aws_inventory', '0.7.0'
@@ -1,5 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # An [apply action](applying_manifest_blocks.md#return-value-of-apply-action)
4
+ # returns an `ApplyResult`. An `ApplyResult` is part of a `ResultSet` object and
5
+ # contains information about the apply action.
6
+ #
7
+ # @param report
8
+ # The Puppet report from the apply action. Equivalent to calling `ApplyResult.value['report']`.
9
+ # The report is a hash representation of the [`Puppet::Transaction::Report`
10
+ # object](https://puppet.com/docs/puppet/latest/format_report.html), where each property
11
+ # corresponds to a key in the report hash. For more information, see [Result
12
+ # keys](applying_manifest_blocks.md#result-keys).
13
+ # @param target
14
+ # The target the result is from.
15
+ #
16
+ # @!method action
17
+ # The action performed. `ApplyResult.action` always returns the string `apply`.
18
+ # @!method error
19
+ # Returns an Error object constructed from the `_error` field of the result's value.
20
+ # @!method message
21
+ # The `_output` field of the result's value.
22
+ # @!method ok
23
+ # Whether the result was successful.
24
+ # @!method to_data
25
+ # A serialized representation of `ApplyResult`.
26
+ # @!method value
27
+ # A hash including the Puppet report from the apply action under a `report` key.
28
+ #
3
29
  Puppet::DataTypes.create_type('ApplyResult') do
4
30
  interface <<-PUPPET
5
31
  attributes => {
@@ -1,5 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The [run_container](plan_functions.md#run_container) plan function returns a
4
+ # `ContainerResult` object. A `ContainerResult` is a standalone object (not part
5
+ # of a `ResultSet`) that includes either the `stdout` and `stderr` values from
6
+ # running the container, or an `_error` object if the container exited with a
7
+ # nonzero exit code.
8
+ #
9
+ # @param value
10
+ # A hash including the `stdout`, `stderr`, and `exit_code` received from the
11
+ # container.
12
+ #
13
+ # @!method []
14
+ # Accesses the value hash directly and returns the value for the key. This
15
+ # function does not use dot notation. Call the function directly on the
16
+ # `ContainerResult`. For example, `$result[key]`.
17
+ # @!method error
18
+ # An object constructed from the `_error` field of the result's value.
19
+ # @!method ok
20
+ # Whether the result was successful.
21
+ # @!method status
22
+ # Either `success` if the result was successful or `failure`.
23
+ # @!method stdout
24
+ # The value of 'stdout' output by the container.
25
+ # @!method stderr
26
+ # The value of 'stderr' output by the container.
27
+ # @!method to_data
28
+ # A serialized representation of `ContainerResult`.
29
+ #
3
30
  Puppet::DataTypes.create_type('ContainerResult') do
4
31
  interface <<-PUPPET
5
32
  attributes => {
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The [`background()` plan function](plan_functions.md#background) returns a
4
+ # `Future` object, which can be passed to the [`wait()` plan
5
+ # function](plan_functions.md#wait) to block on the result of the backgrounded
6
+ # code block.
7
+ #
8
+ # @!method state
9
+ # Either 'running' if the Future is still executing, 'done' if the Future
10
+ # finished successfully, or 'error' if the Future finished with an error.
11
+ #
12
+ Puppet::DataTypes.create_type('Future') do
13
+ interface <<-PUPPET
14
+ attributes => {},
15
+ functions => {
16
+ state => Callable[[], Enum['running', 'done', 'error']],
17
+ }
18
+ PUPPET
19
+
20
+ load_file('bolt/plan_future')
21
+
22
+ # Needed for Puppet to recognize Bolt::Result as a Puppet object when deserializing
23
+ Bolt::PlanFuture.include(Puppet::Pops::Types::PuppetObject)
24
+ implementation_class Bolt::PlanFuture
25
+ end
@@ -1,5 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # `ResourceInstance` objects are used to store the observed and desired state of a
4
+ # target's resource and to track events for the resource. These objects do not
5
+ # modify or interact with a target's resources.
6
+ #
7
+ # > The `ResourceInstance` data type is experimental and might change in a future
8
+ # > release. You can learn more about this data type and how to use it in the
9
+ # > [experimental features
10
+ # > documentation](experimental_features.md#resourceinstance-data-type).
11
+ #
12
+ # @param events
13
+ # Events for the resource.
14
+ # @param desired_state
15
+ # [Attributes](https://puppet.com/docs/puppet/latest/lang_resources.html#attributes) describing
16
+ # the desired state of the resource.
17
+ # @param state
18
+ # [Attributes](https://puppet.com/docs/puppet/latest/lang_resources.html#attributes) describing
19
+ # the observed state of the resource.
20
+ # @param target
21
+ # The resource's target.
22
+ # @param title
23
+ # The [resource title](https://puppet.com/docs/puppet/latest/lang_resources.html#title).
24
+ # @param type
25
+ # The [resource type](https://puppet.com/docs/puppet/latest/lang_resources.html#resource-types).
26
+ #
27
+ # @!method []
28
+ # Accesses the `state` hash directly and returns the value for the specified
29
+ # attribute. This function does not use dot noation. Call the function directly
30
+ # on the `ResourceInstance`. For example, `$resource['ensure']`.
31
+ # @!method add_event(event)
32
+ # Add an event for the resource.
33
+ # @!method overwrite_desired_state(desired_state)
34
+ # Overwrites the desired state of the resource.
35
+ # @!method overwrite_state(state)
36
+ # Overwrites the observed state of the resource.
37
+ # @!method set_desired_state(desired_state)
38
+ # Sets attributes describing the desired state of the resource. Performs a shallow
39
+ # merge with existing desired state.
40
+ # @!method set_state(state)
41
+ # Sets attributes describing the observed state of the resource. Performs a shallow
42
+ # merge with existing state.
43
+ # @!method reference
44
+ # The resources reference string. For example, `File[/etc/puppetlabs]`.
45
+ #
3
46
  Puppet::DataTypes.create_type('ResourceInstance') do
4
47
  interface <<-PUPPET
5
48
  attributes => {
@@ -1,5 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # For each target that you execute an action on, Bolt returns a `Result` object
4
+ # and adds the `Result` to a `ResultSet` object. A `Result` object contains
5
+ # information about the action you executed on the target.
6
+ #
7
+ # @param target
8
+ # The target the result is from.
9
+ # @param value
10
+ # The output or return of executing on the target.
11
+ #
12
+ # @!method []
13
+ # Accesses the `value` hash directly and returns the value for the key. This
14
+ # function does not use dot nation. Call the function directly on the `Result`.
15
+ # For example, `$result['key']`.
16
+ # @!method action
17
+ # The type of result. For example, `task` or `command`.
18
+ # @!method error
19
+ # An object constructed from the `_error` field of the result's `value`.
20
+ # @!method message
21
+ # The `_output` field of the result's value.
22
+ # @!method ok
23
+ # Whether the result was successful.
24
+ # @!method sensitive
25
+ # The `_sensitive` field of the result's value, wrapped in a `Sensitive` object.
26
+ # Call `unwrap()` to extract the value.
27
+ # @!method status
28
+ # Either `success` if the result was successful or `failure`.
29
+ # @!method to_data
30
+ # A serialized representation of `Result`.
31
+ #
3
32
  Puppet::DataTypes.create_type('Result') do
4
33
  interface <<-PUPPET
5
34
  attributes => {
@@ -1,5 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # For each target that you execute an action on, Bolt returns a `Result` object
4
+ # and adds the `Result` to a `ResultSet` object. In the case of [apply
5
+ # actions](applying_manifest_blocks.md), Bolt returns a `ResultSet` with one or
6
+ # more `ApplyResult` objects.
7
+ #
8
+ # @param results
9
+ # All results in the set.
10
+ #
11
+ # @!method []
12
+ # The accessed results. This function does not use dot notation. Call the
13
+ # function directly on the `ResultSet`. For example, `$results[0]`.
14
+ # @!method count
15
+ # The number of results in the set.
16
+ # @!method empty
17
+ # Whether the set is empty.
18
+ # @!method error_set
19
+ # The set of failing results.
20
+ # @!method filter_set
21
+ # Filters a set of results by the contents of the block.
22
+ # @!method find(target_name)
23
+ # Retrieves a result for a specified target.
24
+ # @!method first
25
+ # The first result in the set. Useful for unwrapping single results.
26
+ # @!method names
27
+ # The names of all targets that have a `Result` in the set.
28
+ # @!method ok
29
+ # Whether all results were successful. Equivalent to `$results.error_set.empty`.
30
+ # @!method ok_set
31
+ # The set of successful results.
32
+ # @!method targets
33
+ # The list of targets that have results in the set.
34
+ # @!method to_data
35
+ # An array of serialized representations of each result in the set.
36
+ #
3
37
  Puppet::DataTypes.create_type('ResultSet') do
4
38
  interface <<-PUPPET
5
39
  attributes => {
@@ -1,5 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The `Target` object represents a target and its specific connection options.
4
+ #
5
+ # @param config
6
+ # The inventory configuration for the target. This function returns the
7
+ # configuration set directly on the target in `inventory.yaml` or set in
8
+ # a plan using `Target.new` or `set_config()`. It does not return default
9
+ # configuration values or configuration set in Bolt configuration files.
10
+ # @param facts
11
+ # The target's facts. This function does not look up facts for a target and
12
+ # only returns the facts specified in an `inventory.yaml` file or set on a
13
+ # target during a plan run. To retrieve facts for a target and set them in
14
+ # inventory, run the [facts](writing_plans.md#collect-facts-from-targets)
15
+ # plan or [puppetdb_fact](writing_plans.md#collect-facts-from-puppetdb)
16
+ # plan.
17
+ # @param features
18
+ # The target's features.
19
+ # @param name
20
+ # The target's human-readable name, or its URI if a name was not given.
21
+ # @param plugin_hooks
22
+ # The target's `plugin_hooks` [configuration
23
+ # options](bolt_inventory_reference.md#plugin-hooks-1).
24
+ # @param resources
25
+ # The target's resources. This function does not look up resources for a
26
+ # target and only returns resources set on a target during a plan run.
27
+ # @param safe_name
28
+ # The target's safe name. Equivalent to `name` if a name was given, or the
29
+ # target's `uri` with any password omitted.
30
+ # @param target_alias
31
+ # The target's aliases.
32
+ # @param uri
33
+ # The target's URI.
34
+ # @param vars
35
+ # The target's variables.
36
+ #
37
+ # @!method host
38
+ # The target's hostname.
39
+ # @!method password
40
+ # The password to use when connecting to the target.
41
+ # @!method port
42
+ # The target's connection port.
43
+ # @!method protocol
44
+ # The protocol used to connect to the target. This is equivalent to the target's
45
+ # `transport`, expect for targets using the `remote` transport. For example,
46
+ # a target with the URI `http://example.com` using the `remote` transport would
47
+ # return `http` for the `protocol`.
48
+ # @!method transport
49
+ # The transport used to connect to the target.
50
+ # @!method transport_config
51
+ # The merged configuration for the target's `transport`. This function returns
52
+ # configuration that includes defaults set by Bolt, configuration set in
53
+ # `inventory.yaml`, configuration set in `bolt-defaults.yaml`, and configuration
54
+ # set in a plan using `set_config()`.
55
+ # @!method user
56
+ # The user to connect to the target.
57
+ #
3
58
  Puppet::DataTypes.create_type('Target') do
4
59
  begin
5
60
  inventory = Puppet.lookup(:bolt_inventory)
@@ -8,6 +8,7 @@ require 'bolt/error'
8
8
  Puppet::Functions.create_function(:add_to_group) do
9
9
  # @param targets A pattern or array of patterns identifying a set of targets.
10
10
  # @param group The name of the group to add targets to.
11
+ # @return [Array[Target]] The targets.
11
12
  # @example Add new Target to group.
12
13
  # Target.new('foo@example.com', 'password' => 'secret').add_to_group('group1')
13
14
  # @example Add new target to group by name.
@@ -16,6 +16,8 @@ Puppet::Functions.create_function(:apply_prep) do
16
16
  # @param targets A pattern or array of patterns identifying a set of targets.
17
17
  # @param options Options hash.
18
18
  # @option options [Array] _required_modules An array of modules to sync to the target.
19
+ # @option options [String] _run_as User to run as using privilege escalation.
20
+ # @return [nil]
19
21
  # @example Prepare targets by name.
20
22
  # apply_prep('target1,target2')
21
23
  dispatch :apply_prep do
@@ -70,7 +72,8 @@ Puppet::Functions.create_function(:apply_prep) do
70
72
  .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'apply_prep')
71
73
  end
72
74
 
73
- options = options.transform_keys { |k| k.sub(/^_/, '').to_sym }
75
+ # Unfreeze this
76
+ options = options.slice(*%w[_run_as _required_modules])
74
77
 
75
78
  applicator = Puppet.lookup(:apply_executor)
76
79
 
@@ -78,14 +81,14 @@ Puppet::Functions.create_function(:apply_prep) do
78
81
 
79
82
  targets = inventory.get_targets(target_spec)
80
83
 
81
- required_modules = options[:required_modules].nil? ? nil : Array(options[:required_modules])
82
- if required_modules&.any?
84
+ required_modules = options.delete('_required_modules').to_a
85
+ if required_modules.any?
83
86
  Puppet.debug("Syncing only required modules: #{required_modules.join(',')}.")
84
87
  end
85
88
 
86
89
  # Gather facts, including custom facts
87
90
  plugins = applicator.build_plugin_tarball do |mod|
88
- next unless required_modules.nil? || required_modules.include?(mod.name)
91
+ next unless required_modules.empty? || required_modules.include?(mod.name)
89
92
  search_dirs = []
90
93
  search_dirs << mod.plugins if mod.plugins?
91
94
  search_dirs << mod.pluginfacts if mod.pluginfacts?
@@ -106,8 +109,9 @@ Puppet::Functions.create_function(:apply_prep) do
106
109
  opts = t.plugin_hooks&.fetch('puppet_library').dup
107
110
  plugin_name = opts.delete('plugin')
108
111
  hook = inventory.plugins.get_hook(plugin_name, :puppet_library)
112
+ # Give plan function options precedence over inventory options
109
113
  { 'target' => t,
110
- 'hook_proc' => hook.call(opts, t, self) }
114
+ 'hook_proc' => hook.call(opts.merge(options), t, self) }
111
115
  rescue StandardError => e
112
116
  Bolt::Result.from_exception(t, e)
113
117
  end
@@ -131,7 +135,7 @@ Puppet::Functions.create_function(:apply_prep) do
131
135
 
132
136
  task = applicator.custom_facts_task
133
137
  arguments = { 'plugins' => Puppet::Pops::Types::PSensitiveType::Sensitive.new(plugins) }
134
- results = executor.run_task(targets, task, arguments)
138
+ results = run_task(targets, task, arguments, options)
135
139
 
136
140
  # TODO: Standardize RunFailure type with error above
137
141
  raise Bolt::RunFailure.new(results, 'run_task', task.name) unless results.ok?
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Starts a block of code in parallel with the main plan without blocking.
4
+ # Returns a Future object.
5
+ #
6
+ # > **Note:** Not available in apply block
7
+ Puppet::Functions.create_function(:background, Puppet::Functions::InternalFunction) do
8
+ # Starts a block of code in parallel with the main plan without blocking.
9
+ # Returns a Future object.
10
+ # @param name An optional name for legible logs.
11
+ # @param block The code block to run in the background.
12
+ # @return A Bolt Future object
13
+ # @example Start a long-running process
14
+ # background() || {
15
+ # run_task('superlong::task', $targets)
16
+ # }
17
+ # run_command("echo 'Continue immediately'", $targets)
18
+ dispatch :background do
19
+ scope_param
20
+ optional_param 'String[1]', :name
21
+ block_param 'Callable[0, 0]', :block
22
+ return_type 'Future'
23
+ end
24
+
25
+ def background(scope, name = nil, &block)
26
+ unless Puppet[:tasks]
27
+ raise Puppet::ParseErrorWithIssue
28
+ .from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'background')
29
+ end
30
+
31
+ executor = Puppet.lookup(:bolt_executor)
32
+ executor.report_function_call(self.class.name)
33
+
34
+ executor.create_future(scope: scope, name: name) do |newscope|
35
+ # Catch 'return' calls inside the block
36
+ result = catch(:return) do
37
+ # Execute the block. Individual plan steps in the block will yield
38
+ # the Fiber if they haven't finished, so all this needs to do is run
39
+ # the block.
40
+ block.closure.call_by_name_with_scope(newscope, {}, true)
41
+ end
42
+
43
+ # If we got a return from the block, get its value
44
+ # Otherwise the result is the last line from the block
45
+ result = result.value if result.is_a?(Puppet::Pops::Evaluator::Return)
46
+
47
+ # Validate the result is a PlanResult
48
+ unless Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult').instance?(result)
49
+ raise Bolt::InvalidParallelResult.new(result.to_s, *Puppet::Pops::PuppetStack.top_of_stack)
50
+ end
51
+
52
+ result
53
+ rescue Puppet::PreformattedError => e
54
+ if e.cause.is_a?(Bolt::Error)
55
+ e.cause
56
+ else
57
+ raise e
58
+ end
59
+ end
60
+ end
61
+ end