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,190 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt_spec/bolt_context'
|
4
|
+
require 'bolt_spec/plans/mock_executor'
|
5
|
+
require 'bolt/pal'
|
6
|
+
|
7
|
+
# These helpers are intended to be used for plan unit testing without calling
|
8
|
+
# out to targets. It uses the BoltContext helper to set up a mock executor
|
9
|
+
# which allows calls to run_* functions to be stubbed for testing. The context
|
10
|
+
# helper also loads Bolt datatypes and plan functions to be used by the code
|
11
|
+
# being tested.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
# describe "my_plan" do
|
15
|
+
# it 'should return' do
|
16
|
+
# allow_task('my_task').always_return({'result_key' => 10})
|
17
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to be
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# it 'should call task with param1' do
|
21
|
+
# expect_task('my_task').with_params('param1' => 10).always_return({'result_key' => 10})
|
22
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# it 'should call task with param1 once' do
|
26
|
+
# expect_task('my_task').with_params('param1' => 10).always_return({'result_key' => 10}).be_called_times(1)
|
27
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# it 'should not_call task with 100' do
|
31
|
+
# allow_task('my_task').always_return({'result_key' => 10})
|
32
|
+
# # Any call with param1 => 100 will match this since it's added second
|
33
|
+
# expect_task('my_task').with_params('param1' => 100).not_be_called
|
34
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# it 'should be called on both node1 and node2' do
|
38
|
+
# expect_task('my_task').with_targets(['node1', 'node2']).always_return({'result_key' => 10})
|
39
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# it 'should average results from targets' do
|
43
|
+
# expect_task('my_task').return_for_targets({
|
44
|
+
# 'node1' => {'result_key' => 20},
|
45
|
+
# 'node2' => {'result_key' => 6} })
|
46
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(13)
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# it 'should construct a custom return value' do
|
50
|
+
# expect_task('my_task').return do |targets:, task:, params:|
|
51
|
+
# Bolt::ResultSet.new(targets.map { |targ| Bolt::Result.new(targ, {'result_key' => 10'})})
|
52
|
+
# end
|
53
|
+
# expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# it 'expects multiple messages to out::message' do
|
57
|
+
# expect_out_message.be_called_times(2).with_params(message)
|
58
|
+
# result = run_plan(plan_name, 'messages' => [message, message])
|
59
|
+
# expect(result).to be_ok
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# it 'expects a sub-plan to be called' do
|
63
|
+
# expect_plan('module::sub_plan').with_params('targets' => ['foo']).be_called_times(1)
|
64
|
+
# result = run_plan('module::main_plan', 'targets' => ['foo'])
|
65
|
+
# expect(result).to be_ok
|
66
|
+
# expect(result.class).to eq(Bolt::PlanResult)
|
67
|
+
# expect(result.value).to eq('foo' => 'is_good')
|
68
|
+
# expect(result.status).to eq('success')
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# it 'error when sub-plan is called' do
|
72
|
+
# execute_no_plan
|
73
|
+
# err = 'Unexpected call to 'run_plan(module::sub_plan, {\"targets\"=>[\"foo\"]})'
|
74
|
+
# expect { run_plan('module::main_plan', 'targets' => ['foo']) }
|
75
|
+
# .to raise_error(RuntimeError, err)
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# it 'errors when plan calls fail_plan()' do
|
79
|
+
# result = run_plan('module::calls_fail_plan', {})
|
80
|
+
# expect(result).not_to be_ok
|
81
|
+
# expect(result.class).to eq(Bolt::PlanResult)
|
82
|
+
# expect(result.status).to eq('failure')
|
83
|
+
# expect(result.value.class).to eq(Bolt::PlanFailure)
|
84
|
+
# expect(result.value.msg).to eq('failure message passed to fail_plan()')
|
85
|
+
# expect(result.value.kind).to eq('bolt/plan-failure')
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# See spec/bolt_spec/plan_spec.rb for more examples.
|
90
|
+
module BoltSpec
|
91
|
+
module Plans
|
92
|
+
include BoltSpec::BoltContext
|
93
|
+
|
94
|
+
def self.init
|
95
|
+
# Ensure tasks are enabled when rspec-puppet sets up an environment so we get task loaders.
|
96
|
+
# Note that this is probably not safe to do in modules that also test Puppet manifest code.
|
97
|
+
Bolt::PAL.load_puppet
|
98
|
+
Puppet[:tasks] = true
|
99
|
+
|
100
|
+
# Ensure logger is initialized with Puppet levels so 'notice' works when running plan specs.
|
101
|
+
Logging.init :trace, :debug, :info, :notice, :warn, :error, :fatal
|
102
|
+
end
|
103
|
+
|
104
|
+
# Provided as a class so expectations can be placed on it.
|
105
|
+
class MockPuppetDBClient
|
106
|
+
def initialize(config)
|
107
|
+
@instance = MockPuppetDBInstance.new(config)
|
108
|
+
end
|
109
|
+
|
110
|
+
def instance(_instance)
|
111
|
+
@instance
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class MockPuppetDBInstance
|
116
|
+
attr_reader :config
|
117
|
+
|
118
|
+
def initialize(config)
|
119
|
+
@config = config
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def puppetdb_client
|
124
|
+
@puppetdb_client ||= MockPuppetDBClient.new({})
|
125
|
+
end
|
126
|
+
|
127
|
+
def run_plan(name, params)
|
128
|
+
pal = Bolt::PAL.new(
|
129
|
+
Bolt::Config::Modulepath.new(config.modulepath),
|
130
|
+
config.hiera_config,
|
131
|
+
config.project.resource_types,
|
132
|
+
config.compile_concurrency,
|
133
|
+
config.trusted_external,
|
134
|
+
config.apply_settings,
|
135
|
+
config.project
|
136
|
+
)
|
137
|
+
|
138
|
+
result = executor.with_plan_allowed_exec(name, params) do
|
139
|
+
pal.run_plan(name, params, executor, inventory, puppetdb_client)
|
140
|
+
end
|
141
|
+
|
142
|
+
if executor.error_message
|
143
|
+
raise executor.error_message
|
144
|
+
end
|
145
|
+
|
146
|
+
begin
|
147
|
+
executor.assert_call_expectations
|
148
|
+
rescue StandardError => e
|
149
|
+
raise "#{e.message}\nPlan result: #{result}\n#{e.backtrace.join("\n")}"
|
150
|
+
end
|
151
|
+
|
152
|
+
result
|
153
|
+
end
|
154
|
+
|
155
|
+
def allow_apply_prep
|
156
|
+
allow_task('apply_helpers::custom_facts')
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
|
160
|
+
def allow_apply
|
161
|
+
executor.stub_apply
|
162
|
+
nil
|
163
|
+
end
|
164
|
+
|
165
|
+
def allow_get_resources
|
166
|
+
allow_task('apply_helpers::query_resources')
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
|
170
|
+
# Flag for the default behavior of executing sub-plans during testing
|
171
|
+
# By *default* we allow any sub-plan to be executed, no mocking required.
|
172
|
+
# Users can still mock out plans in this mode and the mocks will check for
|
173
|
+
# parameters and return values like normal. However, if a plan isn't explicitly
|
174
|
+
# mocked out, it will be executed.
|
175
|
+
def execute_any_plan
|
176
|
+
executor.execute_any_plan = true
|
177
|
+
end
|
178
|
+
|
179
|
+
# If you want to explicitly mock out all of the sub-plan calls, then
|
180
|
+
# call this prior to calling `run_plan()` along with setting up any
|
181
|
+
# mocks that you require.
|
182
|
+
# In this mode, any plan that is not explicitly mocked out will not be executed
|
183
|
+
# and an error will be thrown.
|
184
|
+
def execute_no_plan
|
185
|
+
executor.execute_any_plan = false
|
186
|
+
end
|
187
|
+
|
188
|
+
# intended to be private below here
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/analytics'
|
4
|
+
require 'bolt/config'
|
5
|
+
require 'bolt/executor'
|
6
|
+
require 'bolt/inventory'
|
7
|
+
require 'bolt/pal'
|
8
|
+
require 'bolt/plugin'
|
9
|
+
require 'bolt/puppetdb'
|
10
|
+
require 'bolt/util'
|
11
|
+
require 'bolt/logger'
|
12
|
+
|
13
|
+
# This is intended to provide a relatively stable method of executing bolt in process from tests.
|
14
|
+
module BoltSpec
|
15
|
+
module Run
|
16
|
+
def run_task(task_name, targets, params, config: nil, inventory: nil)
|
17
|
+
if config.nil? && defined?(bolt_config)
|
18
|
+
config = bolt_config
|
19
|
+
end
|
20
|
+
|
21
|
+
if inventory.nil? && defined?(bolt_inventory)
|
22
|
+
inventory = bolt_inventory
|
23
|
+
end
|
24
|
+
|
25
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
26
|
+
runner.run_task(task_name, targets, params)
|
27
|
+
end
|
28
|
+
result = result.to_a
|
29
|
+
Bolt::Util.walk_keys(result, &:to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_plan(plan_name, params, config: nil, inventory: nil)
|
33
|
+
if config.nil? && defined?(bolt_config)
|
34
|
+
config = bolt_config
|
35
|
+
end
|
36
|
+
|
37
|
+
if inventory.nil? && defined?(bolt_inventory)
|
38
|
+
inventory = bolt_inventory
|
39
|
+
end
|
40
|
+
|
41
|
+
# Users copying code from run_task may forget that targets is not a parameter for run plan
|
42
|
+
raise ArgumentError, "params must be a hash" unless params.is_a?(Hash)
|
43
|
+
|
44
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
45
|
+
runner.run_plan(plan_name, params)
|
46
|
+
end
|
47
|
+
|
48
|
+
{ "status" => result.status,
|
49
|
+
"value" => JSON.parse(result.value.to_json) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def run_command(command, targets, options: {}, config: nil, inventory: nil)
|
53
|
+
if config.nil? && defined?(bolt_config)
|
54
|
+
config = bolt_config
|
55
|
+
end
|
56
|
+
|
57
|
+
if inventory.nil? && defined?(bolt_inventory)
|
58
|
+
inventory = bolt_inventory
|
59
|
+
end
|
60
|
+
|
61
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
62
|
+
runner.run_command(command, targets, options)
|
63
|
+
end
|
64
|
+
result = result.to_a
|
65
|
+
Bolt::Util.walk_keys(result, &:to_s)
|
66
|
+
end
|
67
|
+
|
68
|
+
def run_script(script, targets, arguments, options: {}, config: nil, inventory: nil)
|
69
|
+
if config.nil? && defined?(bolt_config)
|
70
|
+
config = bolt_config
|
71
|
+
end
|
72
|
+
|
73
|
+
if inventory.nil? && defined?(bolt_inventory)
|
74
|
+
inventory = bolt_inventory
|
75
|
+
end
|
76
|
+
|
77
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
78
|
+
runner.run_script(script, targets, arguments, options)
|
79
|
+
end
|
80
|
+
result = result.to_a
|
81
|
+
Bolt::Util.walk_keys(result, &:to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
def download_file(source, dest, targets, options: {}, config: nil, inventory: nil)
|
85
|
+
if config.nil? && defined?(bolt_config)
|
86
|
+
config = bolt_config
|
87
|
+
end
|
88
|
+
|
89
|
+
if inventory.nil? && defined?(bolt_inventory)
|
90
|
+
inventory = bolt_inventory
|
91
|
+
end
|
92
|
+
|
93
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
94
|
+
runner.download_file(source, dest, targets, options)
|
95
|
+
end
|
96
|
+
result = result.to_a
|
97
|
+
Bolt::Util.walk_keys(result, &:to_s)
|
98
|
+
end
|
99
|
+
|
100
|
+
def upload_file(source, dest, targets, options: {}, config: nil, inventory: nil)
|
101
|
+
if config.nil? && defined?(bolt_config)
|
102
|
+
config = bolt_config
|
103
|
+
end
|
104
|
+
|
105
|
+
if inventory.nil? && defined?(bolt_inventory)
|
106
|
+
inventory = bolt_inventory
|
107
|
+
end
|
108
|
+
|
109
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
110
|
+
runner.upload_file(source, dest, targets, options)
|
111
|
+
end
|
112
|
+
result = result.to_a
|
113
|
+
Bolt::Util.walk_keys(result, &:to_s)
|
114
|
+
end
|
115
|
+
|
116
|
+
def apply_manifest(manifest, targets, execute: false, noop: false, config: nil, inventory: nil)
|
117
|
+
if config.nil? && defined?(bolt_config)
|
118
|
+
config = bolt_config
|
119
|
+
end
|
120
|
+
|
121
|
+
if inventory.nil? && defined?(bolt_inventory)
|
122
|
+
inventory = bolt_inventory
|
123
|
+
end
|
124
|
+
|
125
|
+
# The execute parameter is equivalent to the --execute option
|
126
|
+
if execute
|
127
|
+
code = manifest
|
128
|
+
else
|
129
|
+
begin
|
130
|
+
unless File.stat(manifest).readable?
|
131
|
+
raise Bolt::FileError.new("The manifest '#{manifest}' is unreadable", manifest)
|
132
|
+
end
|
133
|
+
rescue Errno::ENOENT
|
134
|
+
raise Bolt::FileError.new("The manifest '#{manifest}' does not exist", manifest)
|
135
|
+
end
|
136
|
+
code = File.read(File.expand_path(manifest))
|
137
|
+
filename = manifest
|
138
|
+
end
|
139
|
+
result = BoltRunner.with_runner(config, inventory) do |runner|
|
140
|
+
runner.apply_manifest(code, targets, filename, noop)
|
141
|
+
end
|
142
|
+
JSON.parse(result.to_json)
|
143
|
+
end
|
144
|
+
|
145
|
+
class BoltRunner
|
146
|
+
# Creates a temporary project so no settings are picked up
|
147
|
+
# WARNING: puppetdb config and orch config which do not use the project may
|
148
|
+
# still be loaded
|
149
|
+
def self.with_runner(config_data, inventory_data)
|
150
|
+
Dir.mktmpdir do |project_path|
|
151
|
+
runner = new(Bolt::Util.deep_clone(config_data), Bolt::Util.deep_clone(inventory_data), project_path)
|
152
|
+
yield runner
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def initialize(config_data, inventory_data, project_path)
|
157
|
+
Bolt::Logger.initialize_logging
|
158
|
+
|
159
|
+
@config_data = config_data || {}
|
160
|
+
@inventory_data = inventory_data || {}
|
161
|
+
@project_path = project_path
|
162
|
+
@analytics = Bolt::Analytics::NoopClient.new
|
163
|
+
end
|
164
|
+
|
165
|
+
def config
|
166
|
+
@config ||= Bolt::Config.new(Bolt::Project.create_project(@project_path), @config_data)
|
167
|
+
end
|
168
|
+
|
169
|
+
def inventory
|
170
|
+
@inventory ||= Bolt::Inventory.create_version(@inventory_data, config.transport, config.transports, plugins)
|
171
|
+
end
|
172
|
+
|
173
|
+
def plugins
|
174
|
+
@plugins ||= Bolt::Plugin.new(config, pal)
|
175
|
+
end
|
176
|
+
|
177
|
+
def puppetdb_client
|
178
|
+
plugins.puppetdb_client
|
179
|
+
end
|
180
|
+
|
181
|
+
def pal
|
182
|
+
@pal ||= Bolt::PAL.new(Bolt::Config::Modulepath.new(config.modulepath),
|
183
|
+
config.hiera_config,
|
184
|
+
config.project.resource_types,
|
185
|
+
config.compile_concurrency,
|
186
|
+
config.trusted_external,
|
187
|
+
config.apply_settings,
|
188
|
+
config.project)
|
189
|
+
end
|
190
|
+
|
191
|
+
def resolve_targets(target_spec)
|
192
|
+
@inventory.get_targets(target_spec).map(&:name)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Adapted from CLI
|
196
|
+
def run_task(task_name, targets, params, noop: false)
|
197
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics, noop)
|
198
|
+
pal.run_task(task_name, targets, params, executor, inventory, nil) { |_ev| nil }
|
199
|
+
end
|
200
|
+
|
201
|
+
# Adapted from CLI does not handle nodes or plan_job reporting
|
202
|
+
def run_plan(plan_name, params, noop: false)
|
203
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics, noop)
|
204
|
+
pal.run_plan(plan_name, params, executor, inventory, puppetdb_client)
|
205
|
+
end
|
206
|
+
|
207
|
+
def run_command(command, targets, options)
|
208
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics)
|
209
|
+
targets = inventory.get_targets(targets)
|
210
|
+
executor.run_command(targets, command, options)
|
211
|
+
end
|
212
|
+
|
213
|
+
def run_script(script, targets, arguments, options = {})
|
214
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics)
|
215
|
+
targets = inventory.get_targets(targets)
|
216
|
+
executor.run_script(targets, script, arguments, options)
|
217
|
+
end
|
218
|
+
|
219
|
+
def download_file(source, dest, targets, options = {})
|
220
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics)
|
221
|
+
targets = inventory.get_targets(targets)
|
222
|
+
executor.download_file(targets, source, dest, options)
|
223
|
+
end
|
224
|
+
|
225
|
+
def upload_file(source, dest, targets, options = {})
|
226
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics)
|
227
|
+
targets = inventory.get_targets(targets)
|
228
|
+
executor.upload_file(targets, source, dest, options)
|
229
|
+
end
|
230
|
+
|
231
|
+
def apply_manifest(code, targets, filename = nil, noop = false)
|
232
|
+
ast = pal.parse_manifest(code, filename)
|
233
|
+
executor = Bolt::Executor.new(config.concurrency, @analytics, noop)
|
234
|
+
targets = inventory.get_targets(targets)
|
235
|
+
|
236
|
+
pal.in_plan_compiler(executor, inventory, puppetdb_client) do |compiler|
|
237
|
+
compiler.call_function('apply_prep', targets)
|
238
|
+
end
|
239
|
+
|
240
|
+
pal.with_bolt_executor(executor, inventory, puppetdb_client) do
|
241
|
+
Puppet.lookup(:apply_executor).apply_ast(ast, targets, catch_errors: true, noop: noop)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logging'
|
4
|
+
|
5
|
+
module LoggingExtensions
|
6
|
+
# the logging gem always sets itself up to initialize little-plugger
|
7
|
+
# https://github.com/TwP/logging/commit/5aeeffaaa9fe483c2258a23d3b9e92adfafb3b2e
|
8
|
+
# little-plugger calls Gem.find_files, incurring an expensive gem scan
|
9
|
+
def initialize_plugins; end
|
10
|
+
end
|
11
|
+
|
12
|
+
# monkey patch Logging to override the extended method with a no-op
|
13
|
+
Logging.extend(LoggingExtensions)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
#! /opt/puppetlabs/puppet/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
require 'json'
|
6
|
+
require 'puppet'
|
7
|
+
require 'puppet/configurer'
|
8
|
+
require 'puppet/module_tool/tar'
|
9
|
+
require 'securerandom'
|
10
|
+
require 'tempfile'
|
11
|
+
|
12
|
+
args = JSON.parse(ARGV[0] ? File.read(ARGV[0]) : $stdin.read)
|
13
|
+
|
14
|
+
# Create temporary directories for all core Puppet settings so we don't clobber
|
15
|
+
# existing state or read from puppet.conf. Also create a temporary modulepath.
|
16
|
+
# Additionally include rundir, which gets its own initialization.
|
17
|
+
puppet_root = Dir.mktmpdir
|
18
|
+
moduledir = File.join(puppet_root, 'modules')
|
19
|
+
Dir.mkdir(moduledir)
|
20
|
+
cli = (Puppet::Settings::REQUIRED_APP_SETTINGS + [:rundir]).flat_map do |setting|
|
21
|
+
["--#{setting}", File.join(puppet_root, setting.to_s.chomp('dir'))]
|
22
|
+
end
|
23
|
+
cli << '--modulepath' << moduledir
|
24
|
+
Puppet.initialize_settings(cli)
|
25
|
+
|
26
|
+
# Avoid extraneous output
|
27
|
+
Puppet[:report] = false
|
28
|
+
|
29
|
+
# Make sure to apply the catalog
|
30
|
+
Puppet[:noop] = args['_noop'] || false
|
31
|
+
args['apply_settings'].each do |setting, value|
|
32
|
+
Puppet[setting.to_sym] = value
|
33
|
+
end
|
34
|
+
|
35
|
+
Puppet[:default_file_terminus] = :file_server
|
36
|
+
|
37
|
+
exit_code = 0
|
38
|
+
begin
|
39
|
+
# This happens implicitly when running the Configurer, but we make it explicit here. It creates the
|
40
|
+
# directories we configured earlier.
|
41
|
+
Puppet.settings.use(:main)
|
42
|
+
|
43
|
+
Tempfile.open('plugins.tar.gz') do |plugins|
|
44
|
+
File.binwrite(plugins, Base64.decode64(args['plugins']))
|
45
|
+
user = Etc.getpwuid.nil? ? Etc.getlogin : Etc.getpwuid.name
|
46
|
+
Puppet::ModuleTool::Tar.instance.unpack(plugins, moduledir, user)
|
47
|
+
end
|
48
|
+
|
49
|
+
env = Puppet.lookup(:environments).get('production')
|
50
|
+
# Needed to ensure features are loaded
|
51
|
+
env.each_plugin_directory do |dir|
|
52
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
53
|
+
end
|
54
|
+
|
55
|
+
# In the case we are applying on a bolt runner and using bundled-ruby over local transport
|
56
|
+
# we will want to load code shipped with bolt. This is last on the load path and therefore
|
57
|
+
# explicitly packaged plugins should take precedence
|
58
|
+
args['bolt_builtin_content'].each do |builtin_dir|
|
59
|
+
next unless Dir.exist?(builtin_dir)
|
60
|
+
Dir.foreach(builtin_dir) do |dir|
|
61
|
+
unless ['.', '..'].include? dir
|
62
|
+
full_path = File.join(builtin_dir, dir, 'lib')
|
63
|
+
$LOAD_PATH << full_path unless $LOAD_PATH.include?(full_path)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if (conn_info = args['_target'])
|
69
|
+
unless (type = conn_info['remote-transport'])
|
70
|
+
puts "Cannot execute a catalog for a remote target without knowing it's the remote-transport type."
|
71
|
+
exit 1
|
72
|
+
end
|
73
|
+
|
74
|
+
begin
|
75
|
+
require 'puppet/resource_api/transport'
|
76
|
+
rescue LoadError
|
77
|
+
msg = "Could not load 'puppet/resource_api/transport', puppet-resource_api "\
|
78
|
+
"gem version 1.8.0 or greater is required on the proxy target"
|
79
|
+
puts msg
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
|
83
|
+
# Transport.connect will modify this hash!
|
84
|
+
transport_conn_info = conn_info.transform_keys(&:to_sym)
|
85
|
+
|
86
|
+
transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
|
87
|
+
Puppet::ResourceApi::Transport.inject_device(type, transport)
|
88
|
+
|
89
|
+
Puppet[:facts_terminus] = :network_device
|
90
|
+
Puppet[:certname] = conn_info['name']
|
91
|
+
end
|
92
|
+
|
93
|
+
# Ensure custom facts are available for provider suitability tests
|
94
|
+
facts = Puppet::Node::Facts.indirection.find(SecureRandom.uuid, environment: env)
|
95
|
+
|
96
|
+
report = if Puppet::Util::Package.versioncmp(Puppet.version, '5.0.0') > 0
|
97
|
+
Puppet::Transaction::Report.new
|
98
|
+
else
|
99
|
+
Puppet::Transaction::Report.new('apply')
|
100
|
+
end
|
101
|
+
|
102
|
+
overrides = { current_environment: env,
|
103
|
+
loaders: Puppet::Pops::Loaders.new(env) }
|
104
|
+
overrides[:network_device] = true if args['_target']
|
105
|
+
|
106
|
+
Puppet.override(overrides) do
|
107
|
+
catalog = Puppet::Resource::Catalog.from_data_hash(args['catalog'])
|
108
|
+
catalog.environment = env.name.to_s
|
109
|
+
catalog.environment_instance = env
|
110
|
+
if defined?(Puppet::Pops::Evaluator::DeferredResolver)
|
111
|
+
# Only available in Puppet 6
|
112
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(facts, catalog)
|
113
|
+
end
|
114
|
+
catalog = catalog.to_ral
|
115
|
+
|
116
|
+
configurer = Puppet::Configurer.new
|
117
|
+
configurer.run(catalog: catalog, report: report, pluginsync: false)
|
118
|
+
end
|
119
|
+
|
120
|
+
puts JSON.pretty_generate(report.to_data_hash)
|
121
|
+
exit_code = report.exit_status != 1
|
122
|
+
ensure
|
123
|
+
begin
|
124
|
+
FileUtils.remove_dir(puppet_root)
|
125
|
+
rescue Errno::ENOTEMPTY => e
|
126
|
+
$stderr.puts("Could not cleanup temporary directory: #{e}")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
exit exit_code
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bolt'
|
5
|
+
require 'bolt/catalog'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
# This accepts a catalog request on stdin:
|
9
|
+
# { "code_ast": "JSON serialized Puppet AST",
|
10
|
+
# "code_string": "String of code, ignored if AST is provided",
|
11
|
+
# "modulepath": "Array of directories to use as the modulepath for catalog compilation",
|
12
|
+
# "pdb_config": "A hash of PDB client config options as supplied to Bolt",
|
13
|
+
# "hiera_config": "File path to hiera config file",
|
14
|
+
# "target": {
|
15
|
+
# "name": "the name of the node usually fqdn fro url",
|
16
|
+
# "facts": "Hash of facts to use for the node",
|
17
|
+
# "variables": "Hash of variables to use for compilation",
|
18
|
+
# "trusted": "Hash of trusted data for the node"
|
19
|
+
# },
|
20
|
+
# "inventory": JSON serialized information about inventory {
|
21
|
+
# "data": Data stored in inventory @data instance variable,
|
22
|
+
# "target_hash": {
|
23
|
+
# "target_vars": Vars that may have been updated plan,
|
24
|
+
# "target_facts": Facts that may have been updated in plan,
|
25
|
+
# "target_features": Features that may have been updated in plan,
|
26
|
+
# },
|
27
|
+
# "config": {
|
28
|
+
# "transport": Transport to use,
|
29
|
+
# "transports": Array of transport configs (note that transport keys are stringified)
|
30
|
+
# }
|
31
|
+
# }
|
32
|
+
# }
|
33
|
+
|
34
|
+
command = ARGV[0]
|
35
|
+
case command
|
36
|
+
when "parse"
|
37
|
+
code = File.open(ARGV[1], &:read)
|
38
|
+
puts JSON.pretty_generate(Bolt::Catalog.new.generate_ast(code, ARGV[1]))
|
39
|
+
when "compile"
|
40
|
+
request = if ARGV[1]
|
41
|
+
File.open(ARGV[1]) { |fh| JSON.parse(fh.read) }
|
42
|
+
else
|
43
|
+
JSON.parse($stdin.read)
|
44
|
+
end
|
45
|
+
begin
|
46
|
+
catalog = Bolt::Catalog.new.compile_catalog(request)
|
47
|
+
# This seems to be a string in ruby 2.3
|
48
|
+
if catalog.is_a?(String)
|
49
|
+
catalog = JSON.parse(catalog)
|
50
|
+
end
|
51
|
+
puts JSON.pretty_generate(catalog)
|
52
|
+
rescue Puppet::PreformattedError => e
|
53
|
+
message = if e.cause
|
54
|
+
location_info = Puppet::Util::Errors.error_location_with_space(e.file, e.line, e.pos)
|
55
|
+
"#{e.cause.message}#{location_info}"
|
56
|
+
else
|
57
|
+
e.message
|
58
|
+
end
|
59
|
+
puts({ message: message, backtrace: e.backtrace }.to_json)
|
60
|
+
exit 1
|
61
|
+
rescue StandardError => e
|
62
|
+
puts({ message: e.message, backtrace: e.backtrace }.to_json)
|
63
|
+
exit 1
|
64
|
+
end
|
65
|
+
else
|
66
|
+
puts "USAGE: run 'bolt_catalog compile' with a request on STDIN " \
|
67
|
+
"or 'bolt_catalog parse manifest.pp' to generate JSON AST"
|
68
|
+
end
|