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
@@ -0,0 +1,219 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../bolt/error'
|
4
|
+
require_relative '../bolt/logger'
|
5
|
+
require_relative '../bolt/module'
|
6
|
+
require_relative '../bolt/util'
|
7
|
+
|
8
|
+
module Bolt
|
9
|
+
module PlanCreator
|
10
|
+
def self.validate_plan_name(project, plan_name)
|
11
|
+
if project.name.nil?
|
12
|
+
raise Bolt::Error.new(
|
13
|
+
"Project directory '#{project.path}' is not a named project. Unable to create "\
|
14
|
+
"a project-level plan. To name a project, set the 'name' key in the 'bolt-project.yaml' "\
|
15
|
+
"configuration file.",
|
16
|
+
"bolt/unnamed-project-error"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
if plan_name !~ Bolt::Module::CONTENT_NAME_REGEX
|
21
|
+
message = <<~MESSAGE.chomp
|
22
|
+
Invalid plan name '#{plan_name}'. Plan names are composed of one or more name segments
|
23
|
+
separated by double colons '::'.
|
24
|
+
|
25
|
+
Each name segment must begin with a lowercase letter, and can only include lowercase
|
26
|
+
letters, digits, and underscores.
|
27
|
+
|
28
|
+
Examples of valid plan names:
|
29
|
+
- #{project.name}
|
30
|
+
- #{project.name}::my_plan
|
31
|
+
MESSAGE
|
32
|
+
|
33
|
+
raise Bolt::ValidationError, message
|
34
|
+
end
|
35
|
+
|
36
|
+
prefix, _, basename = segment_plan_name(plan_name)
|
37
|
+
|
38
|
+
unless prefix == project.name
|
39
|
+
message = "Incomplete plan name: A plan name must be prefixed with the name of the "\
|
40
|
+
"project or module. Did you mean '#{project.name}::#{plan_name}'?"
|
41
|
+
|
42
|
+
raise Bolt::ValidationError, message
|
43
|
+
end
|
44
|
+
|
45
|
+
%w[pp yaml].each do |ext|
|
46
|
+
next unless (path = project.plans_path + "#{basename}.#{ext}").exist?
|
47
|
+
raise Bolt::Error.new(
|
48
|
+
"A plan with the name '#{plan_name}' already exists at '#{path}', nothing to do.",
|
49
|
+
'bolt/existing-plan-error'
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Create a new plan from the plan templates based on which language the
|
55
|
+
# user configured, and whether the plan wraps a script.
|
56
|
+
#
|
57
|
+
# @param plans_path [string] The path to the new plan
|
58
|
+
# @param plan_name [string] The name of the new plan
|
59
|
+
# @param is_puppet [boolean] Whether to create a Puppet language plan
|
60
|
+
# @param script [string] A reference to a script for the new plan to run
|
61
|
+
#
|
62
|
+
def self.create_plan(plans_path, plan_name, is_puppet: false, script: nil)
|
63
|
+
_, name_segments, basename = segment_plan_name(plan_name)
|
64
|
+
dir_path = plans_path.join(*name_segments)
|
65
|
+
|
66
|
+
begin
|
67
|
+
FileUtils.mkdir_p(dir_path)
|
68
|
+
rescue Errno::EEXIST => e
|
69
|
+
raise Bolt::Error.new(
|
70
|
+
"#{e.message}; unable to create plan directory '#{dir_path}'",
|
71
|
+
'bolt/existing-file-error'
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
type = is_puppet ? 'pp' : 'yaml'
|
76
|
+
plan_path = dir_path + "#{basename}.#{type}"
|
77
|
+
plan_template = if is_puppet && script
|
78
|
+
puppet_script_plan(plan_name, script)
|
79
|
+
elsif is_puppet
|
80
|
+
puppet_plan(plan_name)
|
81
|
+
elsif script
|
82
|
+
yaml_script_plan(script)
|
83
|
+
else
|
84
|
+
yaml_plan(plan_name)
|
85
|
+
end
|
86
|
+
begin
|
87
|
+
File.write(plan_path, plan_template)
|
88
|
+
rescue Errno::EACCES => e
|
89
|
+
raise Bolt::FileError.new(
|
90
|
+
"#{e.message}; unable to create plan",
|
91
|
+
plan_path
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
{ name: plan_name, path: plan_path }
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.segment_plan_name(plan_name)
|
99
|
+
prefix, *name_segments, basename = plan_name.split('::')
|
100
|
+
|
101
|
+
# If the plan name is just the project name, then create an 'init' plan.
|
102
|
+
# Otherwise, use the last name segment for the plan's filename.
|
103
|
+
basename ||= 'init'
|
104
|
+
|
105
|
+
[prefix, name_segments, basename]
|
106
|
+
end
|
107
|
+
|
108
|
+
# Template for a new simple YAML plan.
|
109
|
+
#
|
110
|
+
# @param plan_name [string] The name of the new plan
|
111
|
+
#
|
112
|
+
private_class_method def self.yaml_plan(plan_name)
|
113
|
+
<<~YAML
|
114
|
+
# This is the structure of a simple plan. To learn more about writing
|
115
|
+
# YAML plans, see the documentation: http://pup.pt/bolt-yaml-plans
|
116
|
+
|
117
|
+
# The description sets the description of the plan that will appear
|
118
|
+
# in 'bolt plan show' output.
|
119
|
+
description: A plan created with bolt plan new
|
120
|
+
|
121
|
+
# The parameters key defines the parameters that can be passed to
|
122
|
+
# the plan.
|
123
|
+
parameters:
|
124
|
+
targets:
|
125
|
+
type: TargetSpec
|
126
|
+
description: A list of targets to run actions on
|
127
|
+
default: localhost
|
128
|
+
|
129
|
+
# The steps key defines the actions the plan will take in order.
|
130
|
+
steps:
|
131
|
+
- message: Hello from #{plan_name}
|
132
|
+
- name: command_step
|
133
|
+
command: whoami
|
134
|
+
targets: $targets
|
135
|
+
|
136
|
+
# The return key sets the return value of the plan.
|
137
|
+
return: $command_step
|
138
|
+
YAML
|
139
|
+
end
|
140
|
+
|
141
|
+
# Template for a new YAML plan that runs a script.
|
142
|
+
#
|
143
|
+
# @param script [string] A reference to the script to run.
|
144
|
+
#
|
145
|
+
private_class_method def self.yaml_script_plan(script)
|
146
|
+
<<~YAML
|
147
|
+
# This is the structure of a simple plan. To learn more about writing
|
148
|
+
# YAML plans, see the documentation: http://pup.pt/bolt-yaml-plans
|
149
|
+
|
150
|
+
# The description sets the description of the plan that will appear
|
151
|
+
# in 'bolt plan show' output.
|
152
|
+
description: A plan created with bolt plan new
|
153
|
+
|
154
|
+
# The parameters key defines the parameters that can be passed to
|
155
|
+
# the plan.
|
156
|
+
parameters:
|
157
|
+
targets:
|
158
|
+
type: TargetSpec
|
159
|
+
description: A list of targets to run actions on
|
160
|
+
|
161
|
+
# The steps key defines the actions the plan will take in order.
|
162
|
+
steps:
|
163
|
+
- name: run_script
|
164
|
+
script: #{script}
|
165
|
+
targets: $targets
|
166
|
+
|
167
|
+
# The return key sets the return value of the plan.
|
168
|
+
return: $run_script
|
169
|
+
YAML
|
170
|
+
end
|
171
|
+
|
172
|
+
# Template for a new simple Puppet plan.
|
173
|
+
#
|
174
|
+
# @param plan_name [string] The name of the new plan
|
175
|
+
#
|
176
|
+
private_class_method def self.puppet_plan(plan_name)
|
177
|
+
<<~PUPPET
|
178
|
+
# This is the structure of a simple plan. To learn more about writing
|
179
|
+
# Puppet plans, see the documentation: http://pup.pt/bolt-puppet-plans
|
180
|
+
|
181
|
+
# The summary sets the description of the plan that will appear
|
182
|
+
# in 'bolt plan show' output. Bolt uses puppet-strings to parse the
|
183
|
+
# summary and parameters from the plan.
|
184
|
+
# @summary A plan created with bolt plan new.
|
185
|
+
# @param targets The targets to run on.
|
186
|
+
plan #{plan_name} (
|
187
|
+
TargetSpec $targets = "localhost"
|
188
|
+
) {
|
189
|
+
out::message("Hello from #{plan_name}")
|
190
|
+
$command_result = run_command('whoami', $targets)
|
191
|
+
return $command_result
|
192
|
+
}
|
193
|
+
PUPPET
|
194
|
+
end
|
195
|
+
|
196
|
+
# Template for a new Puppet plan that only runs a script.
|
197
|
+
#
|
198
|
+
# @param plan_name [string] The name of the new plan
|
199
|
+
# @param script [string] A reference to the script to run
|
200
|
+
#
|
201
|
+
private_class_method def self.puppet_script_plan(plan_name, script)
|
202
|
+
<<~PUPPET
|
203
|
+
# This is the structure of a simple plan. To learn more about writing
|
204
|
+
# Puppet plans, see the documentation: http://pup.pt/bolt-puppet-plans
|
205
|
+
|
206
|
+
# The summary sets the description of the plan that will appear
|
207
|
+
# in 'bolt plan show' output. Bolt uses puppet-strings to parse the
|
208
|
+
# summary and parameters from the plan.
|
209
|
+
# @summary A plan created with bolt plan new.
|
210
|
+
# @param targets The targets to run on.
|
211
|
+
plan #{plan_name} (
|
212
|
+
TargetSpec $targets
|
213
|
+
) {
|
214
|
+
return run_script('#{script}', $targets)
|
215
|
+
}
|
216
|
+
PUPPET
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fiber'
|
4
|
+
|
5
|
+
module Bolt
|
6
|
+
class PlanFuture
|
7
|
+
attr_reader :fiber, :id, :scope
|
8
|
+
attr_accessor :value, :plan_stack
|
9
|
+
|
10
|
+
def initialize(fiber, id, plan_id:, name: nil, scope: nil)
|
11
|
+
@fiber = fiber
|
12
|
+
@id = id
|
13
|
+
@name = name
|
14
|
+
@value = nil
|
15
|
+
|
16
|
+
# Default to Puppet's current global_scope, otherwise things will
|
17
|
+
# blow up when the Fiber Executor tries to override the global_scope.
|
18
|
+
@scope = scope || Puppet.lookup(:global_scope) { nil }
|
19
|
+
|
20
|
+
# The plan invocation ID when the Future is created may be
|
21
|
+
# different from the plan ID of the Future when we switch to it if a new
|
22
|
+
# plan was run inside the Future, so keep track of the plans that a
|
23
|
+
# Future is executing in as a stack. When one plan finishes, pop it off
|
24
|
+
# since now we're in the calling plan. These IDs are unique to each plan
|
25
|
+
# invocation, not just plan names.
|
26
|
+
@plan_stack = [plan_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def original_plan
|
30
|
+
@plan_stack.last
|
31
|
+
end
|
32
|
+
|
33
|
+
def current_plan
|
34
|
+
@plan_stack.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def name
|
38
|
+
@name || @id
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"Future '#{name}'"
|
43
|
+
end
|
44
|
+
|
45
|
+
def alive?
|
46
|
+
fiber.alive?
|
47
|
+
end
|
48
|
+
|
49
|
+
def raise(exception)
|
50
|
+
# Make sure the value gets set
|
51
|
+
@value = exception
|
52
|
+
# This was introduced in Ruby 2.7
|
53
|
+
begin
|
54
|
+
# Raise an exception to kill the Fiber. If the Fiber has not been
|
55
|
+
# resumed yet, or is already terminated this will raise a FiberError.
|
56
|
+
# We don't especially care about the FiberError, as long as the Fiber
|
57
|
+
# doesn't report itself as alive.
|
58
|
+
fiber.raise(exception)
|
59
|
+
rescue FiberError
|
60
|
+
# If the Fiber is still alive, resume it with a block to raise the
|
61
|
+
# exception which will terminate it.
|
62
|
+
if fiber.alive?
|
63
|
+
fiber.resume { raise(exception) }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def resume
|
69
|
+
if fiber.alive?
|
70
|
+
@value = fiber.resume
|
71
|
+
else
|
72
|
+
@value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def state
|
77
|
+
if fiber.alive?
|
78
|
+
"running"
|
79
|
+
elsif value.is_a?(Exception)
|
80
|
+
"error"
|
81
|
+
else
|
82
|
+
"done"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative '../bolt/error'
|
5
|
+
require_relative '../bolt/util'
|
6
|
+
|
7
|
+
module Bolt
|
8
|
+
class PlanResult
|
9
|
+
attr_accessor :status, :value
|
10
|
+
|
11
|
+
# This must be called from inside a compiler
|
12
|
+
def self.from_pcore(result, status)
|
13
|
+
result = Bolt::Util.walk_vals(result) do |v|
|
14
|
+
if v.is_a?(Puppet::DataTypes::Error)
|
15
|
+
Bolt::PuppetError.from_error(v)
|
16
|
+
else
|
17
|
+
v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
new(result, status)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(value, status)
|
24
|
+
@value = value
|
25
|
+
@status = status
|
26
|
+
end
|
27
|
+
|
28
|
+
def ok?
|
29
|
+
@status == 'success'
|
30
|
+
end
|
31
|
+
|
32
|
+
def ==(other)
|
33
|
+
value == other.value && status == other.status
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_json(*args)
|
37
|
+
@value.to_json(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
to_json
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require_relative '../../bolt/error'
|
5
|
+
require_relative '../../bolt/util'
|
6
|
+
|
7
|
+
module Bolt
|
8
|
+
class Plugin
|
9
|
+
class Cache
|
10
|
+
attr_reader :reference, :plugin_cache_file, :default_config, :id
|
11
|
+
|
12
|
+
def initialize(reference, plugin_cache_file, default_config)
|
13
|
+
@reference = reference
|
14
|
+
@plugin_cache_file = plugin_cache_file
|
15
|
+
@default_config = default_config
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_and_clean_cache
|
19
|
+
return if ttl == 0
|
20
|
+
validate
|
21
|
+
|
22
|
+
# Luckily we don't need to use a serious hash algorithm
|
23
|
+
require 'digest/bubblebabble'
|
24
|
+
r = reference.reject { |k, _| k == '_cache' }.sort.to_s
|
25
|
+
@id = Digest::SHA2.bubblebabble(r)[0..20]
|
26
|
+
|
27
|
+
unmodified = true
|
28
|
+
# First remove any cache entries past their ttl
|
29
|
+
# This prevents removing plugins from leaving orphaned cache entries
|
30
|
+
cache.delete_if do |_, entry|
|
31
|
+
expired = Time.now - Time.parse(entry['mtime']) >= entry['ttl']
|
32
|
+
unmodified = false if expired
|
33
|
+
expired
|
34
|
+
end
|
35
|
+
File.write(plugin_cache_file, cache.to_json) unless cache.empty? || unmodified
|
36
|
+
|
37
|
+
cache.dig(id, 'result')
|
38
|
+
end
|
39
|
+
|
40
|
+
private def cache
|
41
|
+
@cache ||= Bolt::Util.read_optional_json_file(@plugin_cache_file, 'cache')
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_cache(result)
|
45
|
+
cache.merge!({ id => { 'result' => result,
|
46
|
+
'mtime' => Time.now,
|
47
|
+
'ttl' => ttl } })
|
48
|
+
FileUtils.touch(plugin_cache_file)
|
49
|
+
File.write(plugin_cache_file, cache.to_json)
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate
|
53
|
+
# The default cache `plugin-cache` will be validated by the config
|
54
|
+
# validator
|
55
|
+
return if reference['_cache'].nil?
|
56
|
+
r = reference['_cache']
|
57
|
+
unless r.is_a?(Hash)
|
58
|
+
raise Bolt::ValidationError,
|
59
|
+
"_cache must be a Hash, received #{r.class}: #{r.inspect}"
|
60
|
+
end
|
61
|
+
|
62
|
+
unless r.key?('ttl')
|
63
|
+
raise Bolt::ValidationError, "_cache must set 'ttl' key."
|
64
|
+
end
|
65
|
+
|
66
|
+
unless r['ttl'] >= 0
|
67
|
+
raise Bolt::ValidationError, "'ttl' key under '_cache' must be a minimum of 0."
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private def ttl
|
72
|
+
@ttl ||= reference.dig('_cache', 'ttl') || default_config['ttl']
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
module Bolt
|
5
|
+
class Plugin
|
6
|
+
class EnvVar
|
7
|
+
class InvalidPluginData < Bolt::Plugin::PluginError
|
8
|
+
def initialize(msg, plugin)
|
9
|
+
msg = "Invalid Plugin Data for #{plugin}: #{msg}"
|
10
|
+
super(msg, 'bolt/invalid-plugin-data')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(*_args); end
|
15
|
+
|
16
|
+
def name
|
17
|
+
'env_var'
|
18
|
+
end
|
19
|
+
|
20
|
+
def hooks
|
21
|
+
hook_descriptions.keys
|
22
|
+
end
|
23
|
+
|
24
|
+
def hook_descriptions
|
25
|
+
{
|
26
|
+
resolve_reference: 'Read values stored in environment variables.',
|
27
|
+
validate_resolve_reference: nil
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_resolve_reference(opts)
|
32
|
+
unless opts['var']
|
33
|
+
raise Bolt::ValidationError, "env_var plugin requires that the 'var' is specified"
|
34
|
+
end
|
35
|
+
return if opts['optional'] || opts['default']
|
36
|
+
unless ENV[opts['var']]
|
37
|
+
raise Bolt::ValidationError, "env_var plugin requires that the var '#{opts['var']}' be set"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def resolve_reference(opts)
|
42
|
+
reference = ENV[opts['var']]
|
43
|
+
if opts['json'] && reference
|
44
|
+
begin
|
45
|
+
reference = JSON.parse(reference)
|
46
|
+
rescue JSON::ParserError => e
|
47
|
+
raise InvalidPluginData.new(e.message, name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
reference || opts['default']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|