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,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../bolt/error'
|
4
|
+
require_relative '../../../bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class WinRM < Base
|
10
|
+
OPTIONS = %w[
|
11
|
+
basic-auth-only
|
12
|
+
cacert
|
13
|
+
cleanup
|
14
|
+
connect-timeout
|
15
|
+
extensions
|
16
|
+
file-protocol
|
17
|
+
host
|
18
|
+
interpreters
|
19
|
+
password
|
20
|
+
port
|
21
|
+
realm
|
22
|
+
smb-port
|
23
|
+
ssl
|
24
|
+
ssl-verify
|
25
|
+
tmpdir
|
26
|
+
user
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
DEFAULTS = {
|
30
|
+
"basic-auth-only" => false,
|
31
|
+
"cleanup" => true,
|
32
|
+
"connect-timeout" => 10,
|
33
|
+
"ssl" => true,
|
34
|
+
"ssl-verify" => true,
|
35
|
+
"file-protocol" => "winrm"
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
private def validate
|
39
|
+
super
|
40
|
+
|
41
|
+
if @config['ssl']
|
42
|
+
if @config['file-protocol'] == 'smb'
|
43
|
+
raise Bolt::ValidationError, "SMB file transfers are not allowed with SSL enabled"
|
44
|
+
end
|
45
|
+
|
46
|
+
if @config['cacert']
|
47
|
+
@config['cacert'] = File.expand_path(@config['cacert'], @project)
|
48
|
+
Bolt::Util.validate_file('cacert', @config['cacert'])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if !@config['ssl'] && @config['basic-auth-only']
|
53
|
+
raise Bolt::ValidationError, "Basic auth is only allowed when using SSL"
|
54
|
+
end
|
55
|
+
|
56
|
+
if @config['interpreters']
|
57
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/bolt/config.rb
ADDED
@@ -0,0 +1,515 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'etc'
|
4
|
+
require 'logging'
|
5
|
+
require 'pathname'
|
6
|
+
require_relative '../bolt/project'
|
7
|
+
require_relative '../bolt/logger'
|
8
|
+
require_relative '../bolt/util'
|
9
|
+
require_relative 'config/options'
|
10
|
+
require_relative '../bolt/validator'
|
11
|
+
|
12
|
+
module Bolt
|
13
|
+
class UnknownTransportError < Bolt::Error
|
14
|
+
def initialize(transport, uri = nil)
|
15
|
+
msg = uri.nil? ? "Unknown transport #{transport}" : "Unknown transport #{transport} found for #{uri}"
|
16
|
+
super(msg, 'bolt/unknown-transport')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Config
|
21
|
+
include Bolt::Config::Options
|
22
|
+
|
23
|
+
attr_reader :config_files, :data, :transports, :project, :modified_concurrency
|
24
|
+
|
25
|
+
DEFAULTS_NAME = 'bolt-defaults.yaml'
|
26
|
+
|
27
|
+
# The default concurrency value that is used when the ulimit is not low (i.e. < 700)
|
28
|
+
DEFAULT_DEFAULT_CONCURRENCY = 100
|
29
|
+
|
30
|
+
def self.default
|
31
|
+
new(Bolt::Project.default_project, {})
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.from_project(project, overrides = {})
|
35
|
+
data = load_defaults.push(
|
36
|
+
filepath: project.project_file,
|
37
|
+
data: project.data
|
38
|
+
)
|
39
|
+
|
40
|
+
new(project, data, overrides)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Builds a hash of definitions for transport configuration.
|
44
|
+
#
|
45
|
+
def self.transport_definitions
|
46
|
+
INVENTORY_OPTIONS.each_with_object({}) do |(option, definition), acc|
|
47
|
+
acc[option] = TRANSPORT_CONFIG.key?(option) ? definition.merge(TRANSPORT_CONFIG[option].schema) : definition
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Builds the schema for bolt-defaults.yaml used by the validator.
|
52
|
+
#
|
53
|
+
def self.defaults_schema
|
54
|
+
schema = {
|
55
|
+
type: Hash,
|
56
|
+
properties: DEFAULTS_OPTIONS.map { |opt| [opt, _ref: opt] }.to_h,
|
57
|
+
definitions: OPTIONS.merge(transport_definitions)
|
58
|
+
}
|
59
|
+
|
60
|
+
schema[:definitions]['inventory-config'][:properties] = transport_definitions
|
61
|
+
|
62
|
+
schema
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.system_path
|
66
|
+
if Bolt::Util.windows?
|
67
|
+
Pathname.new(File.join(ENV['ALLUSERSPROFILE'], 'PuppetLabs', 'bolt', 'etc'))
|
68
|
+
else
|
69
|
+
Pathname.new(File.join('/etc', 'puppetlabs', 'bolt'))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.user_path
|
74
|
+
Pathname.new(File.expand_path(File.join('~', '.puppetlabs', 'etc', 'bolt')))
|
75
|
+
rescue StandardError
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# Loads a 'bolt-defaults.yaml' file, which contains default configuration that applies to all
|
80
|
+
# projects. This file does not allow project-specific configuration such as 'hiera-config'
|
81
|
+
# and nests all default inventory configuration under an 'inventory-config' key.
|
82
|
+
def self.load_bolt_defaults_yaml(dir)
|
83
|
+
filepath = dir + DEFAULTS_NAME
|
84
|
+
data = Bolt::Util.read_yaml_hash(filepath, 'config')
|
85
|
+
|
86
|
+
Bolt::Logger.debug("Loaded configuration from #{filepath}")
|
87
|
+
|
88
|
+
# Validate the config against the schema. This will raise a single error
|
89
|
+
# with all validation errors.
|
90
|
+
Bolt::Validator.new.tap do |validator|
|
91
|
+
validator.validate(data, defaults_schema, filepath)
|
92
|
+
validator.warnings.each { |warning| Bolt::Logger.warn(warning[:id], warning[:msg]) }
|
93
|
+
validator.deprecations.each { |dep| Bolt::Logger.deprecate(dep[:id], dep[:msg]) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Remove project-specific config such as hiera-config, etc.
|
97
|
+
project_config = data.slice(*(PROJECT_OPTIONS - DEFAULTS_OPTIONS))
|
98
|
+
|
99
|
+
if project_config.any?
|
100
|
+
data.reject! { |key, _| project_config.include?(key) }
|
101
|
+
|
102
|
+
Bolt::Logger.warn(
|
103
|
+
"unsupported_project_config",
|
104
|
+
"Unsupported project configuration detected in '#{filepath}': #{project_config.keys}. "\
|
105
|
+
"Project configuration should be set in 'bolt-project.yaml'."
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Remove top-level transport config such as transport, ssh, etc.
|
110
|
+
transport_config = data.slice(*INVENTORY_OPTIONS.keys)
|
111
|
+
|
112
|
+
if transport_config.any?
|
113
|
+
data.reject! { |key, _| transport_config.include?(key) }
|
114
|
+
|
115
|
+
Bolt::Logger.warn(
|
116
|
+
"unsupported_inventory_config",
|
117
|
+
"Unsupported inventory configuration detected in '#{filepath}': #{transport_config.keys}. "\
|
118
|
+
"Transport configuration should be set under the 'inventory-config' option or "\
|
119
|
+
"in 'inventory.yaml'."
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Move data under inventory-config to top-level so it can be easily merged with
|
124
|
+
# config from other sources. Error early if inventory-config is not a hash or
|
125
|
+
# has a plugin reference.
|
126
|
+
if data.key?('inventory-config')
|
127
|
+
unless data['inventory-config'].is_a?(Hash)
|
128
|
+
raise Bolt::ValidationError,
|
129
|
+
"Option 'inventory-config' must be of type Hash, received #{data['inventory-config']} "\
|
130
|
+
"#{data['inventory-config']} (file: #{filepath})"
|
131
|
+
end
|
132
|
+
|
133
|
+
if data['inventory-config'].key?('_plugin')
|
134
|
+
raise Bolt::ValidationError,
|
135
|
+
"Found unsupported key '_plugin' for option 'inventory-config'; supported keys are "\
|
136
|
+
"'#{INVENTORY_OPTIONS.keys.join("', '")}' (file: #{filepath})"
|
137
|
+
end
|
138
|
+
|
139
|
+
data = data.merge(data.delete('inventory-config'))
|
140
|
+
end
|
141
|
+
|
142
|
+
{ filepath: filepath, data: data }
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.load_defaults
|
146
|
+
confs = []
|
147
|
+
|
148
|
+
# Load system-level config.
|
149
|
+
if File.exist?(system_path + DEFAULTS_NAME)
|
150
|
+
confs << load_bolt_defaults_yaml(system_path)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Load user-level config if there is a homedir.
|
154
|
+
if user_path && File.exist?(user_path + DEFAULTS_NAME)
|
155
|
+
confs << load_bolt_defaults_yaml(user_path)
|
156
|
+
end
|
157
|
+
|
158
|
+
confs
|
159
|
+
end
|
160
|
+
|
161
|
+
def initialize(project, config_data, overrides = {})
|
162
|
+
unless config_data.is_a?(Array)
|
163
|
+
config_data = [{ filepath: project.project_file, data: config_data }]
|
164
|
+
end
|
165
|
+
|
166
|
+
@logger = Bolt::Logger.logger(self)
|
167
|
+
@project = project
|
168
|
+
@transports = {}
|
169
|
+
@config_files = []
|
170
|
+
|
171
|
+
default_data = {
|
172
|
+
'analytics' => false,
|
173
|
+
'apply-settings' => {},
|
174
|
+
'color' => true,
|
175
|
+
'compile-concurrency' => Etc.nprocessors,
|
176
|
+
'concurrency' => default_concurrency,
|
177
|
+
'disable-warnings' => [],
|
178
|
+
'format' => 'human',
|
179
|
+
'log' => { 'console' => {} },
|
180
|
+
'module-install' => {},
|
181
|
+
'plugin-hooks' => {},
|
182
|
+
'plugins' => {},
|
183
|
+
'puppetdb' => {},
|
184
|
+
'puppetdb-instances' => {},
|
185
|
+
'save-rerun' => true,
|
186
|
+
'spinner' => true,
|
187
|
+
'transport' => 'ssh'
|
188
|
+
}
|
189
|
+
|
190
|
+
if project.path.directory?
|
191
|
+
default_data['log']['bolt-debug.log'] = {
|
192
|
+
'level' => 'debug',
|
193
|
+
'append' => false
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
loaded_data = config_data.each_with_object([]) do |data, acc|
|
198
|
+
if data[:data].any?
|
199
|
+
@config_files.push(data[:filepath])
|
200
|
+
acc.push(data[:data])
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
override_data = normalize_overrides(overrides)
|
205
|
+
|
206
|
+
# If we need to lower concurrency and concurrency is not configured
|
207
|
+
ld_concurrency = loaded_data.map(&:keys).flatten.include?('concurrency')
|
208
|
+
@modified_concurrency = default_concurrency != DEFAULT_DEFAULT_CONCURRENCY &&
|
209
|
+
!ld_concurrency &&
|
210
|
+
!override_data.key?('concurrency')
|
211
|
+
|
212
|
+
@data = merge_config_layers(default_data, *loaded_data, override_data)
|
213
|
+
|
214
|
+
TRANSPORT_CONFIG.each do |transport, config|
|
215
|
+
@transports[transport] = config.new(@data.delete(transport), @project.path)
|
216
|
+
end
|
217
|
+
|
218
|
+
finalize_data
|
219
|
+
validate
|
220
|
+
end
|
221
|
+
|
222
|
+
# Transforms CLI options into a config hash that can be merged with
|
223
|
+
# default and loaded config.
|
224
|
+
def normalize_overrides(options)
|
225
|
+
opts = options.transform_keys(&:to_s)
|
226
|
+
|
227
|
+
# Pull out config options. We need to add 'transport' and 'inventoryfile' as they're
|
228
|
+
# not part of the OPTIONS hash but are valid options that can be set with CLI options
|
229
|
+
overrides = opts.slice(*OPTIONS.keys, 'inventoryfile', 'transport', 'default_puppetdb')
|
230
|
+
|
231
|
+
# Pull out transport config options
|
232
|
+
TRANSPORT_CONFIG.each do |transport, config|
|
233
|
+
overrides[transport] = opts.slice(*config.options)
|
234
|
+
end
|
235
|
+
|
236
|
+
overrides['trace'] = opts['trace'] if opts.key?('trace')
|
237
|
+
|
238
|
+
# Validate the overrides that can have arbitrary values
|
239
|
+
schema = {
|
240
|
+
type: Hash,
|
241
|
+
properties: CLI_OPTIONS.map { |opt| [opt, _ref: opt] }.to_h,
|
242
|
+
definitions: OPTIONS.merge(INVENTORY_OPTIONS)
|
243
|
+
}
|
244
|
+
|
245
|
+
Bolt::Validator.new.validate(overrides.slice(*CLI_OPTIONS), schema, 'command line')
|
246
|
+
|
247
|
+
overrides
|
248
|
+
end
|
249
|
+
|
250
|
+
# Merge configuration from all sources into a single hash. Precedence from lowest to highest:
|
251
|
+
# defaults, system-wide, user-level, project-level, CLI overrides
|
252
|
+
def merge_config_layers(*config_data)
|
253
|
+
config_data.inject({}) do |acc, config|
|
254
|
+
acc.merge(config) do |key, val1, val2|
|
255
|
+
case key
|
256
|
+
# Shallow merge config for each plugin
|
257
|
+
when 'plugins'
|
258
|
+
val1.merge(val2) { |_, v1, v2| v1.merge(v2) }
|
259
|
+
# Transports are deep merged
|
260
|
+
when *TRANSPORT_CONFIG.keys
|
261
|
+
Bolt::Util.deep_merge(val1, val2)
|
262
|
+
# Hash values are shallow merged
|
263
|
+
when 'apply-settings', 'log', 'plugin-hooks', 'puppetdb', 'puppetdb-instances'
|
264
|
+
val1.merge(val2)
|
265
|
+
# Disabled warnings are concatenated
|
266
|
+
when 'disable-warnings'
|
267
|
+
val1.concat(val2)
|
268
|
+
when 'analytics'
|
269
|
+
val1 && val2
|
270
|
+
# All other values are overwritten
|
271
|
+
else
|
272
|
+
val2
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def deep_clone
|
279
|
+
Bolt::Util.deep_clone(self)
|
280
|
+
end
|
281
|
+
|
282
|
+
private def finalize_data
|
283
|
+
if @data['log'].is_a?(Hash)
|
284
|
+
@data['log'] = update_logs(@data['log'])
|
285
|
+
end
|
286
|
+
|
287
|
+
# Expand paths relative to the project. Any settings that came from the
|
288
|
+
# CLI will already be absolute, so the expand will be skipped.
|
289
|
+
if @data.key?('modulepath')
|
290
|
+
moduledirs = if data['modulepath'].is_a?(String)
|
291
|
+
data['modulepath'].split(File::PATH_SEPARATOR)
|
292
|
+
else
|
293
|
+
data['modulepath']
|
294
|
+
end
|
295
|
+
@data['modulepath'] = moduledirs.map do |moduledir|
|
296
|
+
File.expand_path(moduledir, @project.path)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
%w[hiera-config inventoryfile trusted-external-command].each do |opt|
|
301
|
+
@data[opt] = File.expand_path(@data[opt], @project.path) if @data.key?(opt)
|
302
|
+
end
|
303
|
+
|
304
|
+
# Filter hashes to only include valid options
|
305
|
+
%w[apply-settings module-install].each do |opt|
|
306
|
+
@data[opt] = @data[opt].slice(*OPTIONS.dig(opt, :properties).keys)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
private def normalize_log(target)
|
311
|
+
return target if target == 'console'
|
312
|
+
target = target[5..-1] if target.start_with?('file:')
|
313
|
+
'file:' + File.expand_path(target, @project.path)
|
314
|
+
end
|
315
|
+
|
316
|
+
private def update_logs(logs)
|
317
|
+
begin
|
318
|
+
if logs['bolt-debug.log'] && logs['bolt-debug.log'] != 'disable'
|
319
|
+
FileUtils.touch(File.expand_path('bolt-debug.log', @project.path))
|
320
|
+
end
|
321
|
+
rescue StandardError
|
322
|
+
logs.delete('bolt-debug.log')
|
323
|
+
end
|
324
|
+
|
325
|
+
logs.each_with_object({}) do |(key, val), acc|
|
326
|
+
# Remove any disabled logs
|
327
|
+
next if val == 'disable'
|
328
|
+
|
329
|
+
name = normalize_log(key)
|
330
|
+
acc[name] = val.slice('append', 'level').transform_keys(&:to_sym)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
def validate
|
335
|
+
if @data['modulepath']&.include?(@project.managed_moduledir.to_s)
|
336
|
+
raise Bolt::ValidationError,
|
337
|
+
"Found invalid path in modulepath: #{@project.managed_moduledir}. This path "\
|
338
|
+
"is automatically appended to the modulepath and cannot be configured."
|
339
|
+
end
|
340
|
+
|
341
|
+
compile_limit = 2 * Etc.nprocessors
|
342
|
+
unless compile_concurrency < compile_limit
|
343
|
+
raise Bolt::ValidationError, "Compilation is CPU-intensive, set concurrency less than #{compile_limit}"
|
344
|
+
end
|
345
|
+
|
346
|
+
%w[hiera-config trusted-external-command inventoryfile].each do |opt|
|
347
|
+
Bolt::Util.validate_file(opt, @data[opt]) if @data[opt]
|
348
|
+
end
|
349
|
+
|
350
|
+
if File.exist?(default_inventoryfile)
|
351
|
+
Bolt::Util.validate_file('inventory file', default_inventoryfile)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
def default_inventoryfile
|
356
|
+
@project.inventory_file
|
357
|
+
end
|
358
|
+
|
359
|
+
def rerunfile
|
360
|
+
@project.rerunfile
|
361
|
+
end
|
362
|
+
|
363
|
+
def hiera_config
|
364
|
+
@data['hiera-config'] || @project.hiera_config
|
365
|
+
end
|
366
|
+
|
367
|
+
def puppetfile
|
368
|
+
@project.puppetfile
|
369
|
+
end
|
370
|
+
|
371
|
+
def modulepath
|
372
|
+
(@data['modulepath'] || @project.modulepath) + [@project.managed_moduledir.to_s]
|
373
|
+
end
|
374
|
+
|
375
|
+
def modulepath=(value)
|
376
|
+
@data['modulepath'] = Array(value)
|
377
|
+
end
|
378
|
+
|
379
|
+
def plugin_cache
|
380
|
+
@project.plugin_cache || @data['plugin-cache'] || {}
|
381
|
+
end
|
382
|
+
|
383
|
+
def concurrency
|
384
|
+
@data['concurrency']
|
385
|
+
end
|
386
|
+
|
387
|
+
def format
|
388
|
+
@data['format']
|
389
|
+
end
|
390
|
+
|
391
|
+
def format=(value)
|
392
|
+
@data['format'] = value
|
393
|
+
end
|
394
|
+
|
395
|
+
def future
|
396
|
+
@data['future']
|
397
|
+
end
|
398
|
+
|
399
|
+
def trace
|
400
|
+
@data['trace']
|
401
|
+
end
|
402
|
+
|
403
|
+
def log
|
404
|
+
@data['log']
|
405
|
+
end
|
406
|
+
|
407
|
+
def puppetdb
|
408
|
+
@data['puppetdb']
|
409
|
+
end
|
410
|
+
|
411
|
+
def puppetdb_instances
|
412
|
+
@data['puppetdb-instances']
|
413
|
+
end
|
414
|
+
|
415
|
+
def default_puppetdb
|
416
|
+
@data['default_puppetdb']
|
417
|
+
end
|
418
|
+
|
419
|
+
def color
|
420
|
+
@data['color']
|
421
|
+
end
|
422
|
+
|
423
|
+
def save_rerun
|
424
|
+
@data['save-rerun']
|
425
|
+
end
|
426
|
+
|
427
|
+
def spinner
|
428
|
+
@data['spinner']
|
429
|
+
end
|
430
|
+
|
431
|
+
def stream
|
432
|
+
@data['stream']
|
433
|
+
end
|
434
|
+
|
435
|
+
def inventoryfile
|
436
|
+
@data['inventoryfile']
|
437
|
+
end
|
438
|
+
|
439
|
+
def compile_concurrency
|
440
|
+
@data['compile-concurrency']
|
441
|
+
end
|
442
|
+
|
443
|
+
def plugins
|
444
|
+
@data['plugins']
|
445
|
+
end
|
446
|
+
|
447
|
+
def plugin_hooks
|
448
|
+
@data['plugin-hooks']
|
449
|
+
end
|
450
|
+
|
451
|
+
def policies
|
452
|
+
@data['policies']
|
453
|
+
end
|
454
|
+
|
455
|
+
def trusted_external
|
456
|
+
@data['trusted-external-command']
|
457
|
+
end
|
458
|
+
|
459
|
+
def apply_settings
|
460
|
+
@data['apply-settings']
|
461
|
+
end
|
462
|
+
|
463
|
+
def transport
|
464
|
+
@data['transport']
|
465
|
+
end
|
466
|
+
|
467
|
+
def module_install
|
468
|
+
@project.module_install || @data['module-install']
|
469
|
+
end
|
470
|
+
|
471
|
+
def disable_warnings
|
472
|
+
Set.new(@project.disable_warnings + @data['disable-warnings'])
|
473
|
+
end
|
474
|
+
|
475
|
+
def analytics
|
476
|
+
@data['analytics']
|
477
|
+
end
|
478
|
+
|
479
|
+
# Check if there is a case-insensitive match to the path
|
480
|
+
def check_path_case(type, paths)
|
481
|
+
return if paths.nil?
|
482
|
+
matches = matching_paths(paths)
|
483
|
+
|
484
|
+
if matches.any?
|
485
|
+
msg = "WARNING: Bolt is case sensitive when specifying a #{type}. Did you mean:\n"
|
486
|
+
matches.each { |path| msg += " #{path}\n" }
|
487
|
+
Bolt::Logger.warn("path_case", msg)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def matching_paths(paths)
|
492
|
+
Array(paths).map { |p| Dir.glob([p, casefold(p)]) }.flatten.uniq.reject { |p| Array(paths).include?(p) }
|
493
|
+
end
|
494
|
+
|
495
|
+
private def casefold(path)
|
496
|
+
path.chars.map do |l|
|
497
|
+
l =~ /[A-Za-z]/ ? "[#{l.upcase}#{l.downcase}]" : l
|
498
|
+
end.join
|
499
|
+
end
|
500
|
+
|
501
|
+
# Etc::SC_OPEN_MAX is meaningless on windows, not defined in PE Jruby and not available
|
502
|
+
# on some platforms. This method holds the logic to decide whether or not to even consider it.
|
503
|
+
def sc_open_max_available?
|
504
|
+
!Bolt::Util.windows? && defined?(Etc::SC_OPEN_MAX) && Etc.sysconf(Etc::SC_OPEN_MAX)
|
505
|
+
end
|
506
|
+
|
507
|
+
def default_concurrency
|
508
|
+
@default_concurrency ||= if !sc_open_max_available? || Etc.sysconf(Etc::SC_OPEN_MAX) >= 300
|
509
|
+
DEFAULT_DEFAULT_CONCURRENCY
|
510
|
+
else
|
511
|
+
Etc.sysconf(Etc::SC_OPEN_MAX) / 7
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative '../bolt/error'
|
5
|
+
require_relative '../bolt/result'
|
6
|
+
|
7
|
+
module Bolt
|
8
|
+
class ContainerResult
|
9
|
+
attr_reader :value, :object
|
10
|
+
|
11
|
+
def self.from_exception(exception, exit_code, image, position: [])
|
12
|
+
details = Bolt::Result.create_details(position)
|
13
|
+
error = {
|
14
|
+
'kind' => 'puppetlabs.tasks/container-error',
|
15
|
+
'issue_code' => 'CONTAINER_ERROR',
|
16
|
+
'msg' => "Error running container '#{image}': #{exception}",
|
17
|
+
'details' => details
|
18
|
+
}
|
19
|
+
error['details']['exit_code'] = exit_code
|
20
|
+
ContainerResult.new({ '_error' => error }, object: image)
|
21
|
+
end
|
22
|
+
|
23
|
+
def _pcore_init_hash
|
24
|
+
{ 'value' => @value,
|
25
|
+
'object' => @image }
|
26
|
+
end
|
27
|
+
|
28
|
+
# First argument can't be named given the way that Puppet deserializes variables
|
29
|
+
def initialize(value = nil, object: nil)
|
30
|
+
@value = value || {}
|
31
|
+
@object = object
|
32
|
+
end
|
33
|
+
|
34
|
+
def eql?(other)
|
35
|
+
self.class == other.class &&
|
36
|
+
value == other.value
|
37
|
+
end
|
38
|
+
alias == eql?
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
value[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_json(opts = nil)
|
45
|
+
to_data.to_json(opts)
|
46
|
+
end
|
47
|
+
alias to_s to_json
|
48
|
+
|
49
|
+
# This is the value with all non-UTF-8 characters removed, suitable for
|
50
|
+
# printing or converting to JSON. It *should* only be possible to have
|
51
|
+
# non-UTF-8 characters in stdout/stderr keys as they are not allowed from
|
52
|
+
# tasks but we scrub the whole thing just in case.
|
53
|
+
def safe_value
|
54
|
+
Bolt::Util.walk_vals(value) do |val|
|
55
|
+
if val.is_a?(String)
|
56
|
+
# Replace invalid bytes with hex codes, ie. \xDE\xAD\xBE\xEF
|
57
|
+
val.scrub { |c| c.bytes.map { |b| "\\x" + b.to_s(16).upcase }.join }
|
58
|
+
else
|
59
|
+
val
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def stdout
|
65
|
+
value['stdout']
|
66
|
+
end
|
67
|
+
|
68
|
+
def stderr
|
69
|
+
value['stderr']
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_data
|
73
|
+
{
|
74
|
+
"object" => object,
|
75
|
+
"status" => status,
|
76
|
+
"value" => safe_value
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def status
|
81
|
+
ok? ? 'success' : 'failure'
|
82
|
+
end
|
83
|
+
|
84
|
+
def ok?
|
85
|
+
error_hash.nil?
|
86
|
+
end
|
87
|
+
alias ok ok?
|
88
|
+
alias success? ok?
|
89
|
+
|
90
|
+
# This allows access to errors outside puppet compilation
|
91
|
+
# it should be prefered over error in bolt code
|
92
|
+
def error_hash
|
93
|
+
value['_error']
|
94
|
+
end
|
95
|
+
|
96
|
+
# Warning: This will fail outside of a compilation.
|
97
|
+
# Use error_hash inside bolt.
|
98
|
+
# Is it crazy for this to behave differently outside a compiler?
|
99
|
+
def error
|
100
|
+
if error_hash
|
101
|
+
Puppet::DataTypes::Error.from_asserted_hash(error_hash)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|