bolt 3.0.1 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Puppetfile +13 -11
- data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +24 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +20 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -2
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +44 -5
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
- data/bolt-modules/boltlib/types/planresult.pp +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +3 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +20 -2
- data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
- data/lib/bolt/analytics.rb +4 -8
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +6 -3
- data/lib/bolt/cli.rb +123 -37
- data/lib/bolt/config.rb +15 -7
- data/lib/bolt/config/options.rb +62 -12
- data/lib/bolt/config/transport/lxd.rb +23 -0
- data/lib/bolt/config/transport/options.rb +8 -1
- data/lib/bolt/config/transport/podman.rb +33 -0
- data/lib/bolt/container_result.rb +105 -0
- data/lib/bolt/error.rb +15 -0
- data/lib/bolt/executor.rb +37 -18
- data/lib/bolt/inventory/options.rb +9 -0
- data/lib/bolt/inventory/target.rb +16 -0
- data/lib/bolt/logger.rb +8 -0
- data/lib/bolt/module_installer.rb +2 -2
- data/lib/bolt/module_installer/puppetfile.rb +2 -2
- data/lib/bolt/module_installer/specs/forge_spec.rb +2 -2
- data/lib/bolt/module_installer/specs/git_spec.rb +2 -2
- data/lib/bolt/node/output.rb +14 -4
- data/lib/bolt/outputter/human.rb +259 -90
- data/lib/bolt/outputter/json.rb +3 -1
- data/lib/bolt/outputter/logger.rb +17 -0
- data/lib/bolt/pal.rb +25 -4
- data/lib/bolt/pal/yaml_plan.rb +1 -2
- data/lib/bolt/pal/yaml_plan/evaluator.rb +5 -141
- data/lib/bolt/pal/yaml_plan/step.rb +91 -31
- data/lib/bolt/pal/yaml_plan/step/command.rb +21 -13
- data/lib/bolt/pal/yaml_plan/step/download.rb +15 -16
- data/lib/bolt/pal/yaml_plan/step/eval.rb +11 -11
- data/lib/bolt/pal/yaml_plan/step/message.rb +13 -4
- data/lib/bolt/pal/yaml_plan/step/plan.rb +19 -15
- data/lib/bolt/pal/yaml_plan/step/resources.rb +82 -21
- data/lib/bolt/pal/yaml_plan/step/script.rb +36 -17
- data/lib/bolt/pal/yaml_plan/step/task.rb +19 -16
- data/lib/bolt/pal/yaml_plan/step/upload.rb +16 -17
- data/lib/bolt/pal/yaml_plan/transpiler.rb +3 -3
- data/lib/bolt/plan_creator.rb +1 -1
- data/lib/bolt/plugin.rb +13 -11
- data/lib/bolt/project_manager.rb +1 -1
- data/lib/bolt/project_manager/module_migrator.rb +1 -1
- data/lib/bolt/result.rb +11 -15
- data/lib/bolt/shell.rb +16 -0
- data/lib/bolt/shell/bash.rb +61 -31
- data/lib/bolt/shell/bash/tmpdir.rb +2 -2
- data/lib/bolt/shell/powershell.rb +34 -12
- data/lib/bolt/shell/powershell/snippets.rb +30 -3
- data/lib/bolt/task.rb +1 -1
- data/lib/bolt/transport/base.rb +0 -9
- data/lib/bolt/transport/docker.rb +2 -126
- data/lib/bolt/transport/docker/connection.rb +81 -167
- data/lib/bolt/transport/lxd.rb +26 -0
- data/lib/bolt/transport/lxd/connection.rb +99 -0
- data/lib/bolt/transport/orch.rb +13 -5
- data/lib/bolt/transport/podman.rb +19 -0
- data/lib/bolt/transport/podman/connection.rb +98 -0
- data/lib/bolt/transport/ssh/connection.rb +1 -1
- data/lib/bolt/transport/winrm/connection.rb +1 -1
- data/lib/bolt/util.rb +42 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/transport_app.rb +64 -33
- data/lib/bolt_spec/bolt_context.rb +9 -4
- data/lib/bolt_spec/plans.rb +1 -109
- data/lib/bolt_spec/plans/action_stubs.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +8 -1
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +8 -1
- data/lib/bolt_spec/plans/mock_executor.rb +91 -7
- data/modules/puppet_connect/plans/test_input_data.pp +65 -7
- metadata +12 -2
data/lib/bolt/config.rb
CHANGED
@@ -169,6 +169,7 @@ module Bolt
|
|
169
169
|
@config_files = []
|
170
170
|
|
171
171
|
default_data = {
|
172
|
+
'analytics' => true,
|
172
173
|
'apply-settings' => {},
|
173
174
|
'color' => true,
|
174
175
|
'compile-concurrency' => Etc.nprocessors,
|
@@ -263,6 +264,8 @@ module Bolt
|
|
263
264
|
# Disabled warnings are concatenated
|
264
265
|
when 'disable-warnings'
|
265
266
|
val1.concat(val2)
|
267
|
+
when 'analytics'
|
268
|
+
val1 && val2
|
266
269
|
# All other values are overwritten
|
267
270
|
else
|
268
271
|
val2
|
@@ -328,13 +331,6 @@ module Bolt
|
|
328
331
|
end
|
329
332
|
|
330
333
|
def validate
|
331
|
-
if @data['future']
|
332
|
-
Bolt::Logger.warn(
|
333
|
-
"future_option",
|
334
|
-
"Configuration option 'future' no longer exposes future behavior."
|
335
|
-
)
|
336
|
-
end
|
337
|
-
|
338
334
|
if @data['modulepath']&.include?(@project.managed_moduledir.to_s)
|
339
335
|
raise Bolt::ValidationError,
|
340
336
|
"Found invalid path in modulepath: #{@project.managed_moduledir}. This path "\
|
@@ -395,6 +391,10 @@ module Bolt
|
|
395
391
|
@data['format'] = value
|
396
392
|
end
|
397
393
|
|
394
|
+
def future
|
395
|
+
@data['future']
|
396
|
+
end
|
397
|
+
|
398
398
|
def trace
|
399
399
|
@data['trace']
|
400
400
|
end
|
@@ -419,6 +419,10 @@ module Bolt
|
|
419
419
|
@data['spinner']
|
420
420
|
end
|
421
421
|
|
422
|
+
def stream
|
423
|
+
@data['stream']
|
424
|
+
end
|
425
|
+
|
422
426
|
def inventoryfile
|
423
427
|
@data['inventoryfile']
|
424
428
|
end
|
@@ -455,6 +459,10 @@ module Bolt
|
|
455
459
|
Set.new(@project.disable_warnings + @data['disable-warnings'])
|
456
460
|
end
|
457
461
|
|
462
|
+
def analytics
|
463
|
+
@data['analytics']
|
464
|
+
end
|
465
|
+
|
458
466
|
# Check if there is a case-insensitive match to the path
|
459
467
|
def check_path_case(type, paths)
|
460
468
|
return if paths.nil?
|
data/lib/bolt/config/options.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'bolt/config/transport/ssh'
|
4
|
-
require 'bolt/config/transport/winrm'
|
5
|
-
require 'bolt/config/transport/orch'
|
6
|
-
require 'bolt/config/transport/local'
|
7
3
|
require 'bolt/config/transport/docker'
|
4
|
+
require 'bolt/config/transport/local'
|
5
|
+
require 'bolt/config/transport/lxd'
|
6
|
+
require 'bolt/config/transport/orch'
|
7
|
+
require 'bolt/config/transport/podman'
|
8
8
|
require 'bolt/config/transport/remote'
|
9
|
+
require 'bolt/config/transport/ssh'
|
10
|
+
require 'bolt/config/transport/winrm'
|
9
11
|
|
10
12
|
module Bolt
|
11
13
|
class Config
|
@@ -13,12 +15,14 @@ module Bolt
|
|
13
15
|
# Transport config classes. Used to load default transport config which
|
14
16
|
# gets passed along to the inventory.
|
15
17
|
TRANSPORT_CONFIG = {
|
16
|
-
'ssh' => Bolt::Config::Transport::SSH,
|
17
|
-
'winrm' => Bolt::Config::Transport::WinRM,
|
18
|
-
'pcp' => Bolt::Config::Transport::Orch,
|
19
|
-
'local' => Bolt::Config::Transport::Local,
|
20
18
|
'docker' => Bolt::Config::Transport::Docker,
|
21
|
-
'
|
19
|
+
'local' => Bolt::Config::Transport::Local,
|
20
|
+
'lxd' => Bolt::Config::Transport::LXD,
|
21
|
+
'pcp' => Bolt::Config::Transport::Orch,
|
22
|
+
'podman' => Bolt::Config::Transport::Podman,
|
23
|
+
'remote' => Bolt::Config::Transport::Remote,
|
24
|
+
'ssh' => Bolt::Config::Transport::SSH,
|
25
|
+
'winrm' => Bolt::Config::Transport::WinRM
|
22
26
|
}.freeze
|
23
27
|
|
24
28
|
# Plugin definition. This is used by the JSON schemas to indicate that an option
|
@@ -53,6 +57,13 @@ module Bolt
|
|
53
57
|
# Definitions used to validate config options.
|
54
58
|
# https://github.com/puppetlabs/bolt/blob/main/schemas/README.md
|
55
59
|
OPTIONS = {
|
60
|
+
"analytics" => {
|
61
|
+
description: "Whether to disable analytics. Setting this option to 'false' in the system-wide "\
|
62
|
+
"or user-level configuration will disable analytics for all projects, even if this "\
|
63
|
+
"option is set to 'true' at the project level.",
|
64
|
+
type: [TrueClass, FalseClass],
|
65
|
+
_example: false
|
66
|
+
},
|
56
67
|
"apply-settings" => {
|
57
68
|
description: "A map of Puppet settings to use when applying Puppet code using the `apply` "\
|
58
69
|
"plan function or the `bolt apply` command.",
|
@@ -131,6 +142,20 @@ module Bolt
|
|
131
142
|
_example: "json",
|
132
143
|
_default: "human"
|
133
144
|
},
|
145
|
+
"future" => {
|
146
|
+
description: "Enable new Bolt features that may include breaking changes.",
|
147
|
+
type: Hash,
|
148
|
+
properties: {
|
149
|
+
"file_paths" => {
|
150
|
+
description: "Load scripts from the `scripts/` directory of a module",
|
151
|
+
type: [TrueClass, FalseClass],
|
152
|
+
_example: true,
|
153
|
+
_default: false
|
154
|
+
}
|
155
|
+
},
|
156
|
+
_plugin: false,
|
157
|
+
_example: { 'file_paths' => true }
|
158
|
+
},
|
134
159
|
"hiera-config" => {
|
135
160
|
description: "The path to the Hiera configuration file.",
|
136
161
|
type: String,
|
@@ -423,7 +448,14 @@ module Bolt
|
|
423
448
|
_example: false,
|
424
449
|
_default: true
|
425
450
|
},
|
426
|
-
|
451
|
+
"stream" => {
|
452
|
+
description: "Whether to stream output from scripts and commands to the console. "\
|
453
|
+
"**This option is experimental**.",
|
454
|
+
type: [TrueClass, FalseClass],
|
455
|
+
_plugin: false,
|
456
|
+
_default: false,
|
457
|
+
_example: true
|
458
|
+
},
|
427
459
|
"tasks" => {
|
428
460
|
description: "A list of task names and glob patterns to filter the project's tasks by. This option is used "\
|
429
461
|
"to limit the visibility of tasks for users of the project. For example, project authors "\
|
@@ -440,8 +472,8 @@ module Bolt
|
|
440
472
|
},
|
441
473
|
"trusted-external-command" => {
|
442
474
|
description: "The path to an executable on the Bolt controller that can produce external trusted facts. "\
|
443
|
-
"**External trusted facts are experimental in both Puppet and Bolt and this API
|
444
|
-
"be removed.**",
|
475
|
+
"**External trusted facts are experimental in both Puppet and Bolt and this API might "\
|
476
|
+
"change or be removed.**",
|
445
477
|
type: String,
|
446
478
|
_plugin: false,
|
447
479
|
_example: "/etc/puppetlabs/facts/trusted_external.sh"
|
@@ -475,12 +507,25 @@ module Bolt
|
|
475
507
|
_plugin: true,
|
476
508
|
_example: { "cleanup" => false, "tmpdir" => "/tmp/bolt" }
|
477
509
|
},
|
510
|
+
"lxd" => {
|
511
|
+
description: "A map of configuration options for the LXD transport. The LXD transport is "\
|
512
|
+
"experimental and might include breaking changes between minor versions.",
|
513
|
+
type: Hash,
|
514
|
+
_plugin: true,
|
515
|
+
_example: { cleanup: false }
|
516
|
+
},
|
478
517
|
"pcp" => {
|
479
518
|
description: "A map of configuration options for the pcp transport.",
|
480
519
|
type: Hash,
|
481
520
|
_plugin: true,
|
482
521
|
_example: { "job-poll-interval" => 15, "job-poll-timeout" => 30 }
|
483
522
|
},
|
523
|
+
"podman" => {
|
524
|
+
description: "A map of configuration options for the podman transport.",
|
525
|
+
type: Hash,
|
526
|
+
_plugin: true,
|
527
|
+
_example: { "cleanup" => false, "tmpdir" => "/mount/tmp" }
|
528
|
+
},
|
484
529
|
"remote" => {
|
485
530
|
description: "A map of configuration options for the remote transport.",
|
486
531
|
type: Hash,
|
@@ -516,6 +561,7 @@ module Bolt
|
|
516
561
|
|
517
562
|
# Options that are available in a bolt-defaults.yaml file
|
518
563
|
DEFAULTS_OPTIONS = %w[
|
564
|
+
analytics
|
519
565
|
color
|
520
566
|
compile-concurrency
|
521
567
|
concurrency
|
@@ -530,16 +576,19 @@ module Bolt
|
|
530
576
|
puppetdb
|
531
577
|
save-rerun
|
532
578
|
spinner
|
579
|
+
stream
|
533
580
|
].freeze
|
534
581
|
|
535
582
|
# Options that are available in a bolt-project.yaml file
|
536
583
|
PROJECT_OPTIONS = %w[
|
584
|
+
analytics
|
537
585
|
apply-settings
|
538
586
|
color
|
539
587
|
compile-concurrency
|
540
588
|
concurrency
|
541
589
|
disable-warnings
|
542
590
|
format
|
591
|
+
future
|
543
592
|
hiera-config
|
544
593
|
log
|
545
594
|
modulepath
|
@@ -553,6 +602,7 @@ module Bolt
|
|
553
602
|
puppetdb
|
554
603
|
save-rerun
|
555
604
|
spinner
|
605
|
+
stream
|
556
606
|
tasks
|
557
607
|
trusted-external-command
|
558
608
|
].freeze
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class LXD < Base
|
10
|
+
OPTIONS = %w[
|
11
|
+
cleanup
|
12
|
+
remote
|
13
|
+
tmpdir
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
DEFAULTS = {
|
17
|
+
'cleanup' => true,
|
18
|
+
'remote' => 'local'
|
19
|
+
}.freeze
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -32,7 +32,7 @@ module Bolt
|
|
32
32
|
"cleanup" => {
|
33
33
|
type: [TrueClass, FalseClass],
|
34
34
|
description: "Whether to clean up temporary files created on targets. When running commands on a target, "\
|
35
|
-
"Bolt
|
35
|
+
"Bolt might create temporary files. After completing the command, these files are "\
|
36
36
|
"automatically deleted. This value can be set to 'false' if you wish to leave these "\
|
37
37
|
"temporary files on the target.",
|
38
38
|
_plugin: true,
|
@@ -266,6 +266,13 @@ module Bolt
|
|
266
266
|
_plugin: true,
|
267
267
|
_example: "BOLT.PRODUCTION"
|
268
268
|
},
|
269
|
+
"remote" => {
|
270
|
+
type: String,
|
271
|
+
description: "The LXD remote host to use.",
|
272
|
+
_default: "local",
|
273
|
+
_plugin: false,
|
274
|
+
_example: 'myremote'
|
275
|
+
},
|
269
276
|
"run-as" => {
|
270
277
|
type: String,
|
271
278
|
description: "The user to run commands as after login. The run-as user must be different than the "\
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Podman < Base
|
10
|
+
OPTIONS = %w[
|
11
|
+
cleanup
|
12
|
+
host
|
13
|
+
interpreters
|
14
|
+
shell-command
|
15
|
+
tmpdir
|
16
|
+
tty
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
DEFAULTS = {
|
20
|
+
'cleanup' => true
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
private def validate
|
24
|
+
super
|
25
|
+
|
26
|
+
if @config['interpreters']
|
27
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'bolt/error'
|
5
|
+
require '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
|
data/lib/bolt/error.rb
CHANGED
@@ -61,6 +61,21 @@ module Bolt
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
class ContainerFailure < Bolt::Error
|
65
|
+
attr_reader :result
|
66
|
+
|
67
|
+
def initialize(result)
|
68
|
+
details = {
|
69
|
+
'value' => result.value,
|
70
|
+
'object' => result.object
|
71
|
+
}
|
72
|
+
message = "Plan aborted: Running container '#{result.object}' failed."
|
73
|
+
super(message, 'bolt/container-failure', details)
|
74
|
+
@result = result
|
75
|
+
@error_code = 2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
64
79
|
class RunFailure < Bolt::Error
|
65
80
|
attr_reader :result_set
|
66
81
|
|
data/lib/bolt/executor.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
require 'English'
|
5
5
|
require 'json'
|
6
6
|
require 'logging'
|
7
|
+
require 'pathname'
|
7
8
|
require 'set'
|
8
9
|
require 'bolt/analytics'
|
9
10
|
require 'bolt/result'
|
@@ -11,35 +12,39 @@ require 'bolt/config'
|
|
11
12
|
require 'bolt/result_set'
|
12
13
|
require 'bolt/puppetdb'
|
13
14
|
# Load transports
|
14
|
-
require 'bolt/transport/ssh'
|
15
|
-
require 'bolt/transport/winrm'
|
16
|
-
require 'bolt/transport/orch'
|
17
|
-
require 'bolt/transport/local'
|
18
15
|
require 'bolt/transport/docker'
|
16
|
+
require 'bolt/transport/local'
|
17
|
+
require 'bolt/transport/lxd'
|
18
|
+
require 'bolt/transport/orch'
|
19
|
+
require 'bolt/transport/podman'
|
19
20
|
require 'bolt/transport/remote'
|
21
|
+
require 'bolt/transport/ssh'
|
22
|
+
require 'bolt/transport/winrm'
|
20
23
|
require 'bolt/yarn'
|
21
24
|
|
22
25
|
module Bolt
|
23
26
|
TRANSPORTS = {
|
24
|
-
ssh: Bolt::Transport::SSH,
|
25
|
-
winrm: Bolt::Transport::WinRM,
|
26
|
-
pcp: Bolt::Transport::Orch,
|
27
|
-
local: Bolt::Transport::Local,
|
28
27
|
docker: Bolt::Transport::Docker,
|
29
|
-
|
28
|
+
local: Bolt::Transport::Local,
|
29
|
+
lxd: Bolt::Transport::LXD,
|
30
|
+
pcp: Bolt::Transport::Orch,
|
31
|
+
podman: Bolt::Transport::Podman,
|
32
|
+
remote: Bolt::Transport::Remote,
|
33
|
+
ssh: Bolt::Transport::SSH,
|
34
|
+
winrm: Bolt::Transport::WinRM
|
30
35
|
}.freeze
|
31
36
|
|
32
37
|
class Executor
|
33
|
-
attr_reader :noop, :transports, :in_parallel
|
38
|
+
attr_reader :noop, :transports, :in_parallel, :future
|
34
39
|
attr_accessor :run_as
|
35
40
|
|
36
41
|
def initialize(concurrency = 1,
|
37
42
|
analytics = Bolt::Analytics::NoopClient.new,
|
38
43
|
noop = false,
|
39
|
-
modified_concurrency = false
|
44
|
+
modified_concurrency = false,
|
45
|
+
future = {})
|
40
46
|
# lazy-load expensive gem code
|
41
47
|
require 'concurrent'
|
42
|
-
|
43
48
|
@analytics = analytics
|
44
49
|
@logger = Bolt::Logger.logger(self)
|
45
50
|
|
@@ -62,6 +67,7 @@ module Bolt
|
|
62
67
|
@noop = noop
|
63
68
|
@run_as = nil
|
64
69
|
@in_parallel = false
|
70
|
+
@future = future
|
65
71
|
@pool = if concurrency > 0
|
66
72
|
Concurrent::ThreadPoolExecutor.new(name: 'exec', max_threads: concurrency)
|
67
73
|
else
|
@@ -121,8 +127,8 @@ module Bolt
|
|
121
127
|
def queue_execute(targets)
|
122
128
|
if @warn_concurrency && targets.length > @concurrency
|
123
129
|
@warn_concurrency = false
|
124
|
-
msg = "The ulimit is low, which
|
125
|
-
"'#{@concurrency}' to mitigate those issues, which
|
130
|
+
msg = "The ulimit is low, which might cause file limit issues. Default concurrency has been set to "\
|
131
|
+
"'#{@concurrency}' to mitigate those issues, which might cause Bolt to run slow. "\
|
126
132
|
"Disable this warning by configuring ulimit using 'ulimit -n <limit>' in your shell "\
|
127
133
|
"configuration, or by configuring Bolt's concurrency. "\
|
128
134
|
"See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details."
|
@@ -215,7 +221,7 @@ module Bolt
|
|
215
221
|
results
|
216
222
|
end
|
217
223
|
|
218
|
-
def report_transport(transport, count)
|
224
|
+
private def report_transport(transport, count)
|
219
225
|
name = transport.class.name.split('::').last.downcase
|
220
226
|
unless @reported_transports.include?(name)
|
221
227
|
@analytics&.event('Transport', 'initialize', label: name, value: count)
|
@@ -231,6 +237,11 @@ module Bolt
|
|
231
237
|
@analytics.report_bundled_content(mode, name)
|
232
238
|
end
|
233
239
|
|
240
|
+
def report_file_source(plan_function, source)
|
241
|
+
label = Pathname.new(source).absolute? ? 'absolute' : 'module'
|
242
|
+
@analytics&.event('Plan', plan_function, label: label)
|
243
|
+
end
|
244
|
+
|
234
245
|
def report_apply(statement_count, resource_counts)
|
235
246
|
data = { statement_count: statement_count }
|
236
247
|
|
@@ -468,7 +479,7 @@ module Bolt
|
|
468
479
|
Time.now
|
469
480
|
end
|
470
481
|
|
471
|
-
def wait_until(timeout, retry_interval)
|
482
|
+
private def wait_until(timeout, retry_interval)
|
472
483
|
start = wait_now
|
473
484
|
until yield
|
474
485
|
raise(TimeoutError, 'Timed out waiting for target') if (wait_now - start).to_i >= timeout
|
@@ -477,22 +488,30 @@ module Bolt
|
|
477
488
|
end
|
478
489
|
|
479
490
|
def prompt(prompt, options)
|
480
|
-
@prompting = true
|
481
491
|
unless $stdin.tty?
|
492
|
+
return options[:default] if options[:default]
|
482
493
|
raise Bolt::Error.new('STDIN is not a tty, unable to prompt', 'bolt/no-tty-error')
|
483
494
|
end
|
484
495
|
|
485
|
-
|
496
|
+
@prompting = true
|
497
|
+
|
498
|
+
if options[:default] && !options[:sensitive]
|
499
|
+
$stderr.print("#{prompt} [#{options[:default]}]: ")
|
500
|
+
else
|
501
|
+
$stderr.print("#{prompt}: ")
|
502
|
+
end
|
486
503
|
|
487
504
|
value = if options[:sensitive]
|
488
505
|
$stdin.noecho(&:gets).to_s.chomp
|
489
506
|
else
|
490
507
|
$stdin.gets.to_s.chomp
|
491
508
|
end
|
509
|
+
|
492
510
|
@prompting = false
|
493
511
|
|
494
512
|
$stderr.puts if options[:sensitive]
|
495
513
|
|
514
|
+
value = options[:default] if value.empty?
|
496
515
|
value
|
497
516
|
end
|
498
517
|
|