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.
- checksums.yaml +7 -0
- data/Puppetfile +52 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +60 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +51 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/future.rb +25 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +71 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +55 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +65 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +93 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +33 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +38 -0
- data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +208 -0
- data/bolt-modules/boltlib/lib/puppet/functions/background.rb +62 -0
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +57 -0
- data/bolt-modules/boltlib/lib/puppet/functions/download_file.rb +130 -0
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +31 -0
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +52 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +87 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +34 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +35 -0
- data/bolt-modules/boltlib/lib/puppet/functions/parallelize.rb +74 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +97 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +47 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +52 -0
- data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +40 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +42 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resource.rb +53 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +106 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +291 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +145 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +164 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +211 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +48 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +43 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +145 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +38 -0
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +101 -0
- data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +29 -0
- data/bolt-modules/boltlib/lib/puppet/functions/wait.rb +131 -0
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +59 -0
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +39 -0
- data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +50 -0
- data/bolt-modules/boltlib/types/planresult.pp +18 -0
- data/bolt-modules/boltlib/types/targetspec.pp +7 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +42 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +20 -0
- data/bolt-modules/dir/lib/puppet/functions/dir/children.rb +35 -0
- data/bolt-modules/file/lib/puppet/functions/file/delete.rb +21 -0
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +28 -0
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +20 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +33 -0
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +28 -0
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +24 -0
- data/bolt-modules/log/lib/puppet/functions/log/debug.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/error.rb +40 -0
- data/bolt-modules/log/lib/puppet/functions/log/fatal.rb +40 -0
- data/bolt-modules/log/lib/puppet/functions/log/info.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/trace.rb +39 -0
- data/bolt-modules/log/lib/puppet/functions/log/warn.rb +41 -0
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +36 -0
- data/bolt-modules/out/lib/puppet/functions/out/verbose.rb +35 -0
- data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +65 -0
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +20 -0
- data/exe/bolt +17 -0
- data/guides/debugging.yaml +27 -0
- data/guides/inventory.yaml +23 -0
- data/guides/links.yaml +12 -0
- data/guides/logging.yaml +17 -0
- data/guides/module.yaml +18 -0
- data/guides/modulepath.yaml +24 -0
- data/guides/project.yaml +21 -0
- data/guides/targets.yaml +28 -0
- data/guides/transports.yaml +22 -0
- data/lib/bolt/analytics.rb +233 -0
- data/lib/bolt/application.rb +806 -0
- data/lib/bolt/applicator.rb +368 -0
- data/lib/bolt/apply_inventory.rb +93 -0
- data/lib/bolt/apply_result.rb +154 -0
- data/lib/bolt/apply_target.rb +90 -0
- data/lib/bolt/bolt_option_parser.rb +1226 -0
- data/lib/bolt/catalog/logging.rb +15 -0
- data/lib/bolt/catalog.rb +144 -0
- data/lib/bolt/cli.rb +949 -0
- data/lib/bolt/config/modulepath.rb +30 -0
- data/lib/bolt/config/options.rb +673 -0
- data/lib/bolt/config/transport/base.rb +133 -0
- data/lib/bolt/config/transport/docker.rb +34 -0
- data/lib/bolt/config/transport/jail.rb +33 -0
- data/lib/bolt/config/transport/local.rb +39 -0
- data/lib/bolt/config/transport/lxd.rb +34 -0
- data/lib/bolt/config/transport/options.rb +431 -0
- data/lib/bolt/config/transport/orch.rb +41 -0
- data/lib/bolt/config/transport/podman.rb +33 -0
- data/lib/bolt/config/transport/remote.rb +24 -0
- data/lib/bolt/config/transport/ssh.rb +138 -0
- data/lib/bolt/config/transport/winrm.rb +63 -0
- data/lib/bolt/config.rb +515 -0
- data/lib/bolt/container_result.rb +105 -0
- data/lib/bolt/error.rb +194 -0
- data/lib/bolt/executor.rb +539 -0
- data/lib/bolt/fiber_executor.rb +190 -0
- data/lib/bolt/inventory/group.rb +446 -0
- data/lib/bolt/inventory/inventory.rb +391 -0
- data/lib/bolt/inventory/options.rb +139 -0
- data/lib/bolt/inventory/target.rb +293 -0
- data/lib/bolt/inventory.rb +120 -0
- data/lib/bolt/logger.rb +252 -0
- data/lib/bolt/module.rb +54 -0
- data/lib/bolt/module_installer/installer.rb +44 -0
- data/lib/bolt/module_installer/puppetfile/forge_module.rb +54 -0
- data/lib/bolt/module_installer/puppetfile/git_module.rb +37 -0
- data/lib/bolt/module_installer/puppetfile/module.rb +26 -0
- data/lib/bolt/module_installer/puppetfile.rb +131 -0
- data/lib/bolt/module_installer/resolver.rb +129 -0
- data/lib/bolt/module_installer/specs/forge_spec.rb +91 -0
- data/lib/bolt/module_installer/specs/git_spec.rb +150 -0
- data/lib/bolt/module_installer/specs/id/base.rb +116 -0
- data/lib/bolt/module_installer/specs/id/gitclone.rb +120 -0
- data/lib/bolt/module_installer/specs/id/github.rb +90 -0
- data/lib/bolt/module_installer/specs/id/gitlab.rb +92 -0
- data/lib/bolt/module_installer/specs.rb +95 -0
- data/lib/bolt/module_installer.rb +208 -0
- data/lib/bolt/node/errors.rb +55 -0
- data/lib/bolt/node/output.rb +29 -0
- data/lib/bolt/outputter/human.rb +958 -0
- data/lib/bolt/outputter/json.rb +205 -0
- data/lib/bolt/outputter/logger.rb +76 -0
- data/lib/bolt/outputter/rainbow.rb +118 -0
- data/lib/bolt/outputter.rb +57 -0
- data/lib/bolt/pal/issues.rb +19 -0
- data/lib/bolt/pal/logging.rb +17 -0
- data/lib/bolt/pal/yaml_plan/evaluator.rb +83 -0
- data/lib/bolt/pal/yaml_plan/loader.rb +94 -0
- data/lib/bolt/pal/yaml_plan/parameter.rb +63 -0
- data/lib/bolt/pal/yaml_plan/step/command.rb +45 -0
- data/lib/bolt/pal/yaml_plan/step/download.rb +37 -0
- data/lib/bolt/pal/yaml_plan/step/eval.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/message.rb +31 -0
- data/lib/bolt/pal/yaml_plan/step/plan.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/resources.rb +170 -0
- data/lib/bolt/pal/yaml_plan/step/script.rb +62 -0
- data/lib/bolt/pal/yaml_plan/step/task.rb +42 -0
- data/lib/bolt/pal/yaml_plan/step/upload.rb +37 -0
- data/lib/bolt/pal/yaml_plan/step/verbose.rb +31 -0
- data/lib/bolt/pal/yaml_plan/step.rb +223 -0
- data/lib/bolt/pal/yaml_plan/transpiler.rb +90 -0
- data/lib/bolt/pal/yaml_plan.rb +172 -0
- data/lib/bolt/pal.rb +847 -0
- data/lib/bolt/plan_creator.rb +219 -0
- data/lib/bolt/plan_future.rb +86 -0
- data/lib/bolt/plan_result.rb +44 -0
- data/lib/bolt/plugin/cache.rb +76 -0
- data/lib/bolt/plugin/env_var.rb +54 -0
- data/lib/bolt/plugin/module.rb +276 -0
- data/lib/bolt/plugin/prompt.rb +36 -0
- data/lib/bolt/plugin/puppet_connect_data.rb +84 -0
- data/lib/bolt/plugin/puppetdb.rb +124 -0
- data/lib/bolt/plugin/task.rb +72 -0
- data/lib/bolt/plugin.rb +380 -0
- data/lib/bolt/project.rb +219 -0
- data/lib/bolt/project_manager/config_migrator.rb +113 -0
- data/lib/bolt/project_manager/inventory_migrator.rb +67 -0
- data/lib/bolt/project_manager/migrator.rb +39 -0
- data/lib/bolt/project_manager/module_migrator.rb +203 -0
- data/lib/bolt/project_manager.rb +221 -0
- data/lib/bolt/puppetdb/client.rb +153 -0
- data/lib/bolt/puppetdb/config.rb +176 -0
- data/lib/bolt/puppetdb/instance.rb +146 -0
- data/lib/bolt/puppetdb.rb +15 -0
- data/lib/bolt/r10k_log_proxy.rb +30 -0
- data/lib/bolt/rerun.rb +55 -0
- data/lib/bolt/resource_instance.rb +133 -0
- data/lib/bolt/result.rb +247 -0
- data/lib/bolt/result_set.rb +128 -0
- data/lib/bolt/shell/bash/tmpdir.rb +62 -0
- data/lib/bolt/shell/bash.rb +516 -0
- data/lib/bolt/shell/powershell/snippets.rb +181 -0
- data/lib/bolt/shell/powershell.rb +365 -0
- data/lib/bolt/shell.rb +105 -0
- data/lib/bolt/target.rb +174 -0
- data/lib/bolt/task/puppet_server.rb +27 -0
- data/lib/bolt/task/run.rb +55 -0
- data/lib/bolt/task.rb +163 -0
- data/lib/bolt/transport/base.rb +252 -0
- data/lib/bolt/transport/docker/connection.rb +150 -0
- data/lib/bolt/transport/docker.rb +23 -0
- data/lib/bolt/transport/jail/connection.rb +81 -0
- data/lib/bolt/transport/jail.rb +21 -0
- data/lib/bolt/transport/local/connection.rb +106 -0
- data/lib/bolt/transport/local.rb +20 -0
- data/lib/bolt/transport/lxd/connection.rb +115 -0
- data/lib/bolt/transport/lxd.rb +26 -0
- data/lib/bolt/transport/orch/connection.rb +111 -0
- data/lib/bolt/transport/orch.rb +271 -0
- data/lib/bolt/transport/podman/connection.rb +102 -0
- data/lib/bolt/transport/podman.rb +19 -0
- data/lib/bolt/transport/remote.rb +41 -0
- data/lib/bolt/transport/simple.rb +54 -0
- data/lib/bolt/transport/ssh/connection.rb +321 -0
- data/lib/bolt/transport/ssh/exec_connection.rb +140 -0
- data/lib/bolt/transport/ssh.rb +48 -0
- data/lib/bolt/transport/winrm/connection.rb +378 -0
- data/lib/bolt/transport/winrm.rb +33 -0
- data/lib/bolt/util/format.rb +68 -0
- data/lib/bolt/util/puppet_log_level.rb +21 -0
- data/lib/bolt/util.rb +465 -0
- data/lib/bolt/validator.rb +227 -0
- data/lib/bolt/version.rb +5 -0
- data/lib/bolt.rb +8 -0
- data/lib/bolt_server/acl.rb +39 -0
- data/lib/bolt_server/base_config.rb +112 -0
- data/lib/bolt_server/config.rb +64 -0
- data/lib/bolt_server/file_cache.rb +200 -0
- data/lib/bolt_server/request_error.rb +11 -0
- data/lib/bolt_server/schemas/action-check_node_connections.json +14 -0
- data/lib/bolt_server/schemas/action-run_command.json +12 -0
- data/lib/bolt_server/schemas/action-run_script.json +47 -0
- data/lib/bolt_server/schemas/action-run_task.json +20 -0
- data/lib/bolt_server/schemas/action-upload_file.json +47 -0
- data/lib/bolt_server/schemas/partials/target-any.json +10 -0
- data/lib/bolt_server/schemas/partials/target-ssh.json +88 -0
- data/lib/bolt_server/schemas/partials/target-winrm.json +67 -0
- data/lib/bolt_server/schemas/partials/task.json +94 -0
- data/lib/bolt_server/schemas/transport-ssh.json +25 -0
- data/lib/bolt_server/schemas/transport-winrm.json +19 -0
- data/lib/bolt_server/transport_app.rb +554 -0
- data/lib/bolt_spec/bolt_context.rb +226 -0
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +51 -0
- data/lib/bolt_spec/plans/action_stubs/download_stub.rb +66 -0
- data/lib/bolt_spec/plans/action_stubs/plan_stub.rb +55 -0
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +59 -0
- data/lib/bolt_spec/plans/action_stubs/task_stub.rb +57 -0
- data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +65 -0
- data/lib/bolt_spec/plans/action_stubs.rb +196 -0
- data/lib/bolt_spec/plans/mock_executor.rb +361 -0
- data/lib/bolt_spec/plans/publish_stub.rb +49 -0
- data/lib/bolt_spec/plans.rb +190 -0
- data/lib/bolt_spec/run.rb +246 -0
- data/lib/logging_extensions/logging.rb +13 -0
- data/libexec/apply_catalog.rb +130 -0
- data/libexec/bolt_catalog +68 -0
- data/libexec/custom_facts.rb +63 -0
- data/libexec/query_resources.rb +75 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/count.rb +21 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/nodes.rb +22 -0
- data/modules/aggregate/lib/puppet/functions/aggregate/targets.rb +21 -0
- data/modules/aggregate/plans/count.pp +56 -0
- data/modules/aggregate/plans/targets.pp +56 -0
- data/modules/canary/lib/puppet/functions/canary/merge.rb +13 -0
- data/modules/canary/lib/puppet/functions/canary/random_split.rb +22 -0
- data/modules/canary/lib/puppet/functions/canary/skip.rb +25 -0
- data/modules/canary/plans/init.pp +100 -0
- data/modules/puppet_connect/plans/test_input_data.pp +94 -0
- data/modules/puppetdb_fact/plans/init.pp +20 -0
- data/resources/bolt_bash_completion.sh +214 -0
- metadata +735 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4b185096a836ebb48610140607f7cf3d9271f5ac4b849be866ba860bfb9bf39c
|
4
|
+
data.tar.gz: 7012bd8a0ef497bb28941fe60ce248a02ea0d6b521f72610258193ec352be3eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4ca129817353a9743ce4c2fe6252c155a7180f76f7a8520b3ff4262a5b3888598f7c2c1bc2f56825d22ead5329d6461b5e41004569335f55c7363f9b1e5e2f5a
|
7
|
+
data.tar.gz: 81ed93b16ff9acf1edb58604222d21e8ff37922d324df8083e89cf81201bf6782cbd3b62431cb85c8ecf924f26fb9a9cca89b21b2b8402c8a16fd5cc94644a8a
|
data/Puppetfile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
forge 'https://forge.puppetlabs.com'
|
4
|
+
|
5
|
+
moduledir File.join(File.dirname(__FILE__), 'modules')
|
6
|
+
|
7
|
+
# Core modules used by 'apply'
|
8
|
+
mod 'puppetlabs-service', '3.0.0'
|
9
|
+
mod 'puppetlabs-puppet_agent', '4.21.0'
|
10
|
+
mod 'puppetlabs-facts', '1.6.0'
|
11
|
+
|
12
|
+
# Core types and providers for Puppet 6
|
13
|
+
mod 'puppetlabs-augeas_core', '1.5.0'
|
14
|
+
mod 'puppetlabs-host_core', '1.3.0'
|
15
|
+
mod 'puppetlabs-scheduled_task', '4.0.0'
|
16
|
+
mod 'puppetlabs-sshkeys_core', '2.5.0'
|
17
|
+
mod 'puppetlabs-zfs_core', '1.6.1'
|
18
|
+
mod 'puppetlabs-cron_core', '1.3.0'
|
19
|
+
mod 'puppetlabs-mount_core', '1.3.0'
|
20
|
+
mod 'puppetlabs-selinux_core', '1.4.0'
|
21
|
+
mod 'puppetlabs-yumrepo_core', '2.1.0'
|
22
|
+
mod 'puppetlabs-zone_core', '1.2.0'
|
23
|
+
|
24
|
+
# Useful additional modules
|
25
|
+
mod 'puppetlabs-package', '3.0.1'
|
26
|
+
mod 'puppetlabs-puppet_conf', '2.0.0'
|
27
|
+
mod 'puppetlabs-reboot', '5.0.0'
|
28
|
+
mod 'puppetlabs-stdlib', '9.6.0'
|
29
|
+
|
30
|
+
# Task helpers
|
31
|
+
mod 'puppetlabs-powershell_task_helper', '0.1.0'
|
32
|
+
mod 'puppetlabs-ruby_task_helper', '0.6.1'
|
33
|
+
mod 'puppetlabs-ruby_plugin_helper', '0.2.0'
|
34
|
+
mod 'puppetlabs-python_task_helper', '0.5.0'
|
35
|
+
mod 'puppetlabs-bash_task_helper', '2.1.1'
|
36
|
+
|
37
|
+
# Plugin modules
|
38
|
+
mod 'puppetlabs-aws_inventory', '0.7.0'
|
39
|
+
mod 'puppetlabs-azure_inventory', '0.5.0'
|
40
|
+
mod 'puppetlabs-gcloud_inventory', '0.3.0'
|
41
|
+
mod 'puppetlabs-http_request', '0.3.1'
|
42
|
+
mod 'puppetlabs-pkcs7', '0.1.2'
|
43
|
+
mod 'puppetlabs-secure_env_vars', '0.2.0'
|
44
|
+
mod 'puppetlabs-terraform', '0.7.1'
|
45
|
+
mod 'puppetlabs-vault', '0.4.0'
|
46
|
+
mod 'puppetlabs-yaml', '0.2.0'
|
47
|
+
|
48
|
+
# If we don't list these modules explicitly, r10k will purge them
|
49
|
+
mod 'canary', local: true
|
50
|
+
mod 'aggregate', local: true
|
51
|
+
mod 'puppetdb_fact', local: true
|
52
|
+
mod 'puppet_connect', local: true
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
# @param error
|
16
|
+
# An Error object constructed from the `_error` field of the result's value.
|
17
|
+
# @param catalog
|
18
|
+
# The Puppet catalog used to configure the target. The catalog describes the
|
19
|
+
# desired state of the target. The catalog is masked with the `Sensitive` data
|
20
|
+
# type to protect any sensitive information in the catalog from being printed
|
21
|
+
# to the console or logs. Using this function automatically unwraps the
|
22
|
+
# catalog. For more information about catalogs and the catalog compilation
|
23
|
+
# process, see [Catalog
|
24
|
+
# compilation](https://puppet.com/docs/puppet/latest/subsystem_catalog_compilation.html).
|
25
|
+
|
26
|
+
#
|
27
|
+
# @!method action
|
28
|
+
# The action performed. `ApplyResult.action` always returns the string `apply`.
|
29
|
+
# @!method message
|
30
|
+
# The `_output` field of the result's value.
|
31
|
+
# @!method ok
|
32
|
+
# Whether the result was successful.
|
33
|
+
# @!method to_data
|
34
|
+
# A serialized representation of `ApplyResult`.
|
35
|
+
# @!method value
|
36
|
+
# A hash including the Puppet report from the apply action under a `report` key.
|
37
|
+
#
|
38
|
+
Puppet::DataTypes.create_type('ApplyResult') do
|
39
|
+
interface <<-PUPPET
|
40
|
+
attributes => {
|
41
|
+
'report' => Hash[String[1], Data],
|
42
|
+
'target' => Target,
|
43
|
+
'error' => Optional[Error],
|
44
|
+
'catalog' => Optional[Hash]
|
45
|
+
},
|
46
|
+
functions => {
|
47
|
+
ok => Callable[[], Boolean],
|
48
|
+
message => Callable[[], Optional[String]],
|
49
|
+
action => Callable[[], String],
|
50
|
+
to_data => Callable[[], Hash],
|
51
|
+
value => Callable[[], Hash]
|
52
|
+
}
|
53
|
+
PUPPET
|
54
|
+
|
55
|
+
load_file('bolt/apply_result')
|
56
|
+
|
57
|
+
# Needed for Puppet to recognize Bolt::ApplyResult as a Puppet object when deserializing
|
58
|
+
Bolt::ApplyResult.include(Puppet::Pops::Types::PuppetObject)
|
59
|
+
implementation_class Bolt::ApplyResult
|
60
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
30
|
+
Puppet::DataTypes.create_type('ContainerResult') do
|
31
|
+
interface <<-PUPPET
|
32
|
+
attributes => {
|
33
|
+
'value' => Hash[String[1], Data],
|
34
|
+
},
|
35
|
+
functions => {
|
36
|
+
'[]' => Callable[[String[1]], Data],
|
37
|
+
error => Callable[[], Optional[Error]],
|
38
|
+
ok => Callable[[], Boolean],
|
39
|
+
status => Callable[[], String],
|
40
|
+
stdout => Callable[[], String],
|
41
|
+
stderr => Callable[[], String],
|
42
|
+
to_data => Callable[[], Hash]
|
43
|
+
}
|
44
|
+
PUPPET
|
45
|
+
|
46
|
+
load_file('bolt/container_result')
|
47
|
+
|
48
|
+
# Needed for Puppet to recognize Bolt::ContainerResult as a Puppet object when deserializing
|
49
|
+
Bolt::ContainerResult.include(Puppet::Pops::Types::PuppetObject)
|
50
|
+
implementation_class Bolt::ContainerResult
|
51
|
+
end
|
@@ -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
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
46
|
+
Puppet::DataTypes.create_type('ResourceInstance') do
|
47
|
+
interface <<-PUPPET
|
48
|
+
attributes => {
|
49
|
+
'target' => Target,
|
50
|
+
'type' => Variant[String[1], Type[Resource]],
|
51
|
+
'title' => String[1],
|
52
|
+
'state' => Optional[Hash[String[1], Data]],
|
53
|
+
'desired_state' => Optional[Hash[String[1], Data]],
|
54
|
+
'events' => Optional[Array[Hash[String[1], Data]]]
|
55
|
+
},
|
56
|
+
functions => {
|
57
|
+
add_event => Callable[[Hash[String[1], Data]], Array[Hash[String[1], Data]]],
|
58
|
+
set_state => Callable[[Hash[String[1], Data]], Hash[String[1], Data]],
|
59
|
+
overwrite_state => Callable[[Hash[String[1], Data]], Hash[String[1], Data]],
|
60
|
+
set_desired_state => Callable[[Hash[String[1], Data]], Hash[String[1], Data]],
|
61
|
+
overwrite_desired_state => Callable[[Hash[String[1], Data]], Hash[String[1], Data]],
|
62
|
+
reference => Callable[[], String],
|
63
|
+
'[]' => Callable[[String[1]], Data]
|
64
|
+
}
|
65
|
+
PUPPET
|
66
|
+
|
67
|
+
load_file('bolt/resource_instance')
|
68
|
+
# Needed for Puppet to recognize Bolt::ResourceInstance as a Puppet object when deserializing
|
69
|
+
Bolt::ResourceInstance.include(Puppet::Pops::Types::PuppetObject)
|
70
|
+
implementation_class Bolt::ResourceInstance
|
71
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
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 notation. 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
|
+
#
|
32
|
+
Puppet::DataTypes.create_type('Result') do
|
33
|
+
interface <<-PUPPET
|
34
|
+
attributes => {
|
35
|
+
'value' => Hash[String[1], Data],
|
36
|
+
'target' => Target
|
37
|
+
},
|
38
|
+
functions => {
|
39
|
+
error => Callable[[], Optional[Error]],
|
40
|
+
message => Callable[[], Optional[String]],
|
41
|
+
sensitive => Callable[[], Optional[Sensitive[Data]]],
|
42
|
+
action => Callable[[], String],
|
43
|
+
status => Callable[[], String],
|
44
|
+
to_data => Callable[[], Hash],
|
45
|
+
ok => Callable[[], Boolean],
|
46
|
+
'[]' => Callable[[String[1]], Variant[Data, Sensitive[Data]]]
|
47
|
+
}
|
48
|
+
PUPPET
|
49
|
+
|
50
|
+
load_file('bolt/result')
|
51
|
+
|
52
|
+
# Needed for Puppet to recognize Bolt::Result as a Puppet object when deserializing
|
53
|
+
Bolt::Result.include(Puppet::Pops::Types::PuppetObject)
|
54
|
+
implementation_class Bolt::Result
|
55
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
37
|
+
Puppet::DataTypes.create_type('ResultSet') do
|
38
|
+
interface <<-PUPPET
|
39
|
+
attributes => {
|
40
|
+
'results' => Array[Variant[Result, ApplyResult]],
|
41
|
+
},
|
42
|
+
functions => {
|
43
|
+
count => Callable[[], Integer],
|
44
|
+
empty => Callable[[], Boolean],
|
45
|
+
error_set => Callable[[], ResultSet],
|
46
|
+
filter_set => Callable[[Callable], ResultSet],
|
47
|
+
find => Callable[[String[1]], Optional[Variant[Result, ApplyResult]]],
|
48
|
+
first => Callable[[], Optional[Variant[Result, ApplyResult]]],
|
49
|
+
names => Callable[[], Array[String[1]]],
|
50
|
+
ok => Callable[[], Boolean],
|
51
|
+
ok_set => Callable[[], ResultSet],
|
52
|
+
targets => Callable[[], Array[Target]],
|
53
|
+
to_data => Callable[[], Array[Hash]],
|
54
|
+
'[]' => Variant[Callable[[Integer], Optional[Variant[Result, ApplyResult, Array[Variant[Result, ApplyResult]]]]],
|
55
|
+
Callable[[Integer, Integer], Optional[Variant[Result, ApplyResult, Array[Variant[Result, ApplyResult]]]]]
|
56
|
+
]
|
57
|
+
}
|
58
|
+
PUPPET
|
59
|
+
|
60
|
+
load_file('bolt/result_set')
|
61
|
+
|
62
|
+
# Needed for Puppet to recognize Bolt::ResultSet as a Puppet object when deserializing
|
63
|
+
Bolt::ResultSet.include(Puppet::Pops::Types::PuppetObject)
|
64
|
+
implementation_class Bolt::ResultSet
|
65
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
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
|
+
#
|
58
|
+
Puppet::DataTypes.create_type('Target') do
|
59
|
+
begin
|
60
|
+
inventory = Puppet.lookup(:bolt_inventory)
|
61
|
+
target_implementation_class = inventory.target_implementation_class
|
62
|
+
rescue Puppet::Context::UndefinedBindingError
|
63
|
+
target_implementation_class = Bolt::Target
|
64
|
+
end
|
65
|
+
|
66
|
+
interface <<-PUPPET
|
67
|
+
attributes => {
|
68
|
+
uri => { type => Optional[String[1]], kind => given_or_derived },
|
69
|
+
name => { type => Optional[String[1]] , kind => given_or_derived },
|
70
|
+
safe_name => { type => Optional[String[1]], kind => given_or_derived },
|
71
|
+
target_alias => { type => Optional[Variant[String[1], Array[String[1]]]], kind => given_or_derived },
|
72
|
+
config => { type => Optional[Hash[String[1], Data]], kind => given_or_derived },
|
73
|
+
vars => { type => Optional[Hash[String[1], Data]], kind => given_or_derived },
|
74
|
+
facts => { type => Optional[Hash[String[1], Data]], kind => given_or_derived },
|
75
|
+
features => { type => Optional[Array[String[1]]], kind => given_or_derived },
|
76
|
+
plugin_hooks => { type => Optional[Hash[String[1], Data]], kind => given_or_derived },
|
77
|
+
resources => { type => Optional[Hash[String[1], ResourceInstance]], kind => given_or_derived }
|
78
|
+
},
|
79
|
+
functions => {
|
80
|
+
host => Callable[[], Optional[String]],
|
81
|
+
password => Callable[[], Optional[String[1]]],
|
82
|
+
port => Callable[[], Optional[Integer]],
|
83
|
+
protocol => Callable[[], Optional[String[1]]],
|
84
|
+
transport => Callable[[], String[1]],
|
85
|
+
transport_config => Callable[[], Hash[String[1], Data]],
|
86
|
+
user => Callable[[], Optional[String[1]]]
|
87
|
+
}
|
88
|
+
PUPPET
|
89
|
+
|
90
|
+
# Needed for Puppet to recognize targets as Puppet objects when deserializing
|
91
|
+
target_implementation_class.include(Puppet::Pops::Types::PuppetObject)
|
92
|
+
implementation_class target_implementation_class
|
93
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
# Deep merges a hash of facts with the existing facts on a target.
|
6
|
+
#
|
7
|
+
# > **Note:** Not available in apply block
|
8
|
+
Puppet::Functions.create_function(:add_facts) do
|
9
|
+
# @param target A target.
|
10
|
+
# @param facts A hash of fact names to values that can include structured facts.
|
11
|
+
# @return A `Target` object.
|
12
|
+
# @example Adding facts to a target
|
13
|
+
# add_facts($target, { 'os' => { 'family' => 'windows', 'name' => 'windows' } })
|
14
|
+
dispatch :add_facts do
|
15
|
+
param 'Target', :target
|
16
|
+
param 'Hash', :facts
|
17
|
+
return_type 'Target'
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_facts(target, facts)
|
21
|
+
unless Puppet[:tasks]
|
22
|
+
raise Puppet::ParseErrorWithIssue
|
23
|
+
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'add_facts')
|
24
|
+
end
|
25
|
+
|
26
|
+
inventory = Puppet.lookup(:bolt_inventory)
|
27
|
+
executor = Puppet.lookup(:bolt_executor)
|
28
|
+
# Send Analytics Report
|
29
|
+
executor.report_function_call(self.class.name)
|
30
|
+
|
31
|
+
inventory.add_facts(target, facts)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
|
5
|
+
# Adds a target to specified inventory group.
|
6
|
+
#
|
7
|
+
# > **Note:** Not available in apply block
|
8
|
+
Puppet::Functions.create_function(:add_to_group) do
|
9
|
+
# @param targets A pattern or array of patterns identifying a set of targets.
|
10
|
+
# @param group The name of the group to add targets to.
|
11
|
+
# @return [Array[Target]] The targets.
|
12
|
+
# @example Add new Target to group.
|
13
|
+
# Target.new('foo@example.com', 'password' => 'secret').add_to_group('group1')
|
14
|
+
# @example Add new target to group by name.
|
15
|
+
# add_to_group('bolt:bolt@web.com', 'group1')
|
16
|
+
# @example Add an array of targets to group by name.
|
17
|
+
# add_to_group(['host1', 'group1', 'winrm://host2:54321'], 'group1')
|
18
|
+
# @example Add a comma separated list list of targets to group by name.
|
19
|
+
# add_to_group('foo,bar,baz', 'group1')
|
20
|
+
dispatch :add_to_group do
|
21
|
+
param 'Boltlib::TargetSpec', :targets
|
22
|
+
param 'String[1]', :group
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_to_group(targets, group)
|
26
|
+
unless Puppet[:tasks]
|
27
|
+
raise Puppet::ParseErrorWithIssue
|
28
|
+
.from_issue_and_stack(Bolt::PAL::Issues::PLAN_OPERATION_NOT_SUPPORTED_WHEN_COMPILING, action: 'add_to_group')
|
29
|
+
end
|
30
|
+
|
31
|
+
inventory = Puppet.lookup(:bolt_inventory)
|
32
|
+
executor = Puppet.lookup(:bolt_executor)
|
33
|
+
# Send Analytics Report
|
34
|
+
executor.report_function_call(self.class.name)
|
35
|
+
|
36
|
+
inventory.add_to_group(inventory.get_targets(targets), group)
|
37
|
+
end
|
38
|
+
end
|