bolt 2.15.0 → 2.16.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/bolt-modules/boltlib/lib/puppet/functions/add_facts.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/add_to_group.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/catch_errors.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/facts.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/fail_plan.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_resources.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_target.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_fact.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/remove_from_group.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resolve_references.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/resource.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +2 -1
- data/bolt-modules/boltlib/lib/puppet/functions/set_config.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_feature.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_var.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/vars.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/wait_until_available.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/without_default_logging.rb +1 -0
- data/bolt-modules/boltlib/lib/puppet/functions/write_file.rb +1 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/do_until.rb +2 -0
- data/bolt-modules/ctrl/lib/puppet/functions/ctrl/sleep.rb +2 -0
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +1 -0
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +2 -0
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +2 -0
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +2 -0
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +2 -0
- data/bolt-modules/out/lib/puppet/functions/out/message.rb +2 -0
- data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +1 -0
- data/bolt-modules/system/lib/puppet/functions/system/env.rb +2 -0
- data/lib/bolt/applicator.rb +2 -1
- data/lib/bolt/bolt_option_parser.rb +7 -7
- data/lib/bolt/cli.rb +3 -4
- data/lib/bolt/config.rb +14 -117
- data/lib/bolt/config/options.rb +321 -0
- data/lib/bolt/config/transport/base.rb +16 -16
- data/lib/bolt/config/transport/docker.rb +9 -23
- data/lib/bolt/config/transport/local.rb +6 -44
- data/lib/bolt/config/transport/options.rb +305 -0
- data/lib/bolt/config/transport/orch.rb +9 -18
- data/lib/bolt/config/transport/remote.rb +3 -6
- data/lib/bolt/config/transport/ssh.rb +55 -149
- data/lib/bolt/config/transport/winrm.rb +18 -47
- data/lib/bolt/inventory/group.rb +1 -1
- data/lib/bolt/inventory/inventory.rb +0 -14
- data/lib/bolt/inventory/target.rb +18 -5
- data/lib/bolt/pal.rb +3 -1
- data/lib/bolt/project.rb +21 -38
- data/lib/bolt/shell/bash.rb +9 -9
- data/lib/bolt/shell/powershell.rb +2 -1
- data/lib/bolt/transport/docker.rb +1 -1
- data/lib/bolt/version.rb +1 -1
- metadata +4 -2
@@ -7,24 +7,15 @@ module Bolt
|
|
7
7
|
class Config
|
8
8
|
module Transport
|
9
9
|
class Orch < Base
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
"job-poll-timeout" => { type: Integer,
|
20
|
-
desc: "Set time to wait for orchestrator job status." },
|
21
|
-
"service-url" => { type: String,
|
22
|
-
desc: "The URL of the orchestrator API." },
|
23
|
-
"task-environment" => { type: String,
|
24
|
-
desc: "The environment the orchestrator loads task code from." },
|
25
|
-
"token-file" => { type: String,
|
26
|
-
desc: "The path to the token file." }
|
27
|
-
}.freeze
|
10
|
+
OPTIONS = %w[
|
11
|
+
cacert
|
12
|
+
host
|
13
|
+
job-poll-interval
|
14
|
+
job-poll-timeout
|
15
|
+
service-url
|
16
|
+
task-environment
|
17
|
+
token-file
|
18
|
+
].freeze
|
28
19
|
|
29
20
|
DEFAULTS = {
|
30
21
|
"task-environment" => "production"
|
@@ -7,12 +7,9 @@ module Bolt
|
|
7
7
|
class Config
|
8
8
|
module Transport
|
9
9
|
class Remote < Base
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
"run-on" => { type: String,
|
14
|
-
desc: "The proxy target that the task executes on." }
|
15
|
-
}.freeze
|
10
|
+
OPTIONS = %w[
|
11
|
+
run-on
|
12
|
+
].freeze
|
16
13
|
|
17
14
|
DEFAULTS = {
|
18
15
|
"run-on" => "localhost"
|
@@ -7,148 +7,68 @@ module Bolt
|
|
7
7
|
class Config
|
8
8
|
module Transport
|
9
9
|
class SSH < Base
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
"([docs](https://github.com/net-ssh/net-ssh#supported-algorithms)). "\
|
50
|
-
"All supported, non-deprecated algorithms are available by default when "\
|
51
|
-
"this option is not used. To reference all default algorithms "\
|
52
|
-
"using this option, add 'defaults' to the list of supported "\
|
53
|
-
"algorithms." },
|
54
|
-
"host-key-check" => { type: TrueClass,
|
55
|
-
external: true,
|
56
|
-
desc: "Whether to perform host key validation when connecting." },
|
57
|
-
"interpreters" => { type: Hash,
|
58
|
-
external: true,
|
59
|
-
desc: "A map of an extension name to the absolute path of an executable, "\
|
60
|
-
"enabling you to override the shebang defined in a task executable. "\
|
61
|
-
"The extension can optionally be specified with the `.` character "\
|
62
|
-
"(`.py` and `py` both map to a task executable `task.py`) and the "\
|
63
|
-
"extension is case sensitive. When a target's name is `localhost`, "\
|
64
|
-
"Ruby tasks run with the Bolt Ruby interpreter by default." },
|
65
|
-
"kex-algorithms" => { type: Array,
|
66
|
-
desc: "List of key exchange algorithms to use when establishing a "\
|
67
|
-
"connection to a target. Supported algorithms are defined by the "\
|
68
|
-
"Ruby net-ssh library "\
|
69
|
-
"([docs](https://github.com/net-ssh/net-ssh#supported-algorithms)). "\
|
70
|
-
"All supported, non-deprecated algorithms are available by default when "\
|
71
|
-
"this option is not used. To reference all default algorithms "\
|
72
|
-
"using this option, add 'defaults' to the list of supported "\
|
73
|
-
"algorithms." },
|
74
|
-
"load-config" => { type: TrueClass,
|
75
|
-
desc: "Whether to load system SSH configuration." },
|
76
|
-
"login-shell" => { type: String,
|
77
|
-
desc: "Which login shell Bolt should expect on the target. "\
|
78
|
-
"Supported shells are #{LOGIN_SHELLS.join(', ')}. "\
|
79
|
-
"**This option is experimental.**" },
|
80
|
-
"mac-algorithms" => { type: Array,
|
81
|
-
desc: "List of message authentication code algorithms to use when "\
|
82
|
-
"establishing a connection to a target. Supported algorithms are "\
|
83
|
-
"defined by the Ruby net-ssh library "\
|
84
|
-
"([docs](https://github.com/net-ssh/net-ssh#supported-algorithms)). "\
|
85
|
-
"All supported, non-deprecated algorithms are available by default when "\
|
86
|
-
"this option is not used. To reference all default algorithms "\
|
87
|
-
"using this option, add 'defaults' to the list of supported "\
|
88
|
-
"algorithms." },
|
89
|
-
"password" => { type: String,
|
90
|
-
desc: "Login password." },
|
91
|
-
"port" => { type: Integer,
|
92
|
-
external: true,
|
93
|
-
desc: "Connection port." },
|
94
|
-
"private-key" => { external: true,
|
95
|
-
desc: "Either the path to the private key file to use for authentication, or "\
|
96
|
-
"a hash with the key `key-data` and the contents of the private key." },
|
97
|
-
"proxyjump" => { type: String,
|
98
|
-
desc: "A jump host to proxy connections through, and an optional user to "\
|
99
|
-
"connect with." },
|
100
|
-
"run-as" => { type: String,
|
101
|
-
external: true,
|
102
|
-
desc: "A different user to run commands as after login." },
|
103
|
-
"run-as-command" => { type: Array,
|
104
|
-
external: true,
|
105
|
-
desc: "The command to elevate permissions. Bolt appends the user and command "\
|
106
|
-
"strings to the configured `run-as-command` before running it on the "\
|
107
|
-
"target. This command must not require an interactive password prompt, "\
|
108
|
-
"and the `sudo-password` option is ignored when `run-as-command` is "\
|
109
|
-
"specified. The `run-as-command` must be specified as an array." },
|
110
|
-
"script-dir" => { type: String,
|
111
|
-
external: true,
|
112
|
-
desc: "The subdirectory of the tmpdir to use in place of a randomized "\
|
113
|
-
"subdirectory for uploading and executing temporary files on the "\
|
114
|
-
"target. It's expected that this directory already exists as a subdir "\
|
115
|
-
"of tmpdir, which is either configured or defaults to `/tmp`." },
|
116
|
-
"ssh-command" => { external: true,
|
117
|
-
desc: "Command and flags to use when SSHing. This enables the external "\
|
118
|
-
"SSH transport which shells out to the specified command. "\
|
119
|
-
"**This option is experimental.**" },
|
120
|
-
"sudo-executable" => { type: String,
|
121
|
-
external: true,
|
122
|
-
desc: "The executable to use when escalating to the configured `run-as` "\
|
123
|
-
"user. This is useful when you want to escalate using the configured "\
|
124
|
-
"`sudo-password`, since `run-as-command` does not use `sudo-password` "\
|
125
|
-
"or support prompting. The command executed on the target is "\
|
126
|
-
"`<sudo-executable> -S -u <user> -p custom_bolt_prompt <command>`. "\
|
127
|
-
"**This option is experimental.**" },
|
128
|
-
"sudo-password" => { type: String,
|
129
|
-
external: true,
|
130
|
-
desc: "Password to use when changing users via `run-as`." },
|
131
|
-
"tmpdir" => { type: String,
|
132
|
-
external: true,
|
133
|
-
desc: "The directory to upload and execute temporary files on the target." },
|
134
|
-
"tty" => { type: TrueClass,
|
135
|
-
desc: "Request a pseudo tty for the session. This option is generally "\
|
136
|
-
"only used in conjunction with the `run-as` option when the sudoers "\
|
137
|
-
"policy requires a `tty`." },
|
138
|
-
"user" => { type: String,
|
139
|
-
external: true,
|
140
|
-
desc: "Login user." }
|
141
|
-
}.freeze
|
10
|
+
# Options available when using the net-ssh-based transport
|
11
|
+
OPTIONS = %w[
|
12
|
+
cleanup
|
13
|
+
connect-timeout
|
14
|
+
disconnect-timeout
|
15
|
+
encryption-algorithms
|
16
|
+
extensions
|
17
|
+
host
|
18
|
+
host-key-algorithms
|
19
|
+
host-key-check
|
20
|
+
interpreters
|
21
|
+
kex-algorithms
|
22
|
+
load-config
|
23
|
+
login-shell
|
24
|
+
mac-algorithms
|
25
|
+
password
|
26
|
+
port
|
27
|
+
private-key
|
28
|
+
proxyjump
|
29
|
+
script-dir
|
30
|
+
tmpdir
|
31
|
+
tty
|
32
|
+
user
|
33
|
+
].concat(RUN_AS_OPTIONS).sort.freeze
|
34
|
+
|
35
|
+
# Options available when using the external ssh transport
|
36
|
+
EXTERNAL_OPTIONS = %w[
|
37
|
+
cleanup
|
38
|
+
copy-command
|
39
|
+
host
|
40
|
+
host-key-check
|
41
|
+
interpreters
|
42
|
+
port
|
43
|
+
private-key
|
44
|
+
script-dir
|
45
|
+
ssh-command
|
46
|
+
tmpdir
|
47
|
+
user
|
48
|
+
].concat(RUN_AS_OPTIONS).sort.freeze
|
142
49
|
|
143
50
|
DEFAULTS = {
|
144
51
|
"cleanup" => true,
|
145
52
|
"connect-timeout" => 10,
|
146
|
-
"tty" => false,
|
147
|
-
"load-config" => true,
|
148
53
|
"disconnect-timeout" => 5,
|
149
|
-
"
|
54
|
+
"load-config" => true,
|
55
|
+
"login-shell" => 'bash',
|
56
|
+
"tty" => false
|
150
57
|
}.freeze
|
151
58
|
|
59
|
+
# The set of options available for the ssh and external ssh transports overlap, so we
|
60
|
+
# need to check which transport is used before fully initializing, otherwise options
|
61
|
+
# may not be filtered correctly.
|
62
|
+
def initialize(data = {}, project = nil)
|
63
|
+
assert_hash_or_config(data)
|
64
|
+
@external = true if data['ssh-command']
|
65
|
+
super(data, project)
|
66
|
+
end
|
67
|
+
|
68
|
+
private def filter(unfiltered)
|
69
|
+
@external ? unfiltered.slice(*EXTERNAL_OPTIONS) : unfiltered.slice(*OPTIONS)
|
70
|
+
end
|
71
|
+
|
152
72
|
private def validate
|
153
73
|
super
|
154
74
|
|
@@ -201,20 +121,6 @@ module Bolt
|
|
201
121
|
msg = 'Cannot use external SSH transport with load-config set to false'
|
202
122
|
raise Bolt::ValidationError, msg
|
203
123
|
end
|
204
|
-
|
205
|
-
if (ssh_cmd = @config['ssh-command'])
|
206
|
-
unless ssh_cmd.is_a?(String) || ssh_cmd.is_a?(Array)
|
207
|
-
raise Bolt::ValidationError,
|
208
|
-
"ssh-command must be a String or Array, received #{ssh_cmd.class} #{ssh_cmd.inspect}"
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
if (copy_cmd = @config['copy-command'])
|
213
|
-
unless copy_cmd.is_a?(String) || copy_cmd.is_a?(Array)
|
214
|
-
raise Bolt::ValidationError,
|
215
|
-
"copy-command must be a String or Array, received #{copy_cmd.class} #{copy_cmd.inspect}"
|
216
|
-
end
|
217
|
-
end
|
218
124
|
end
|
219
125
|
end
|
220
126
|
end
|
@@ -7,53 +7,24 @@ module Bolt
|
|
7
7
|
class Config
|
8
8
|
module Transport
|
9
9
|
class WinRM < Base
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
desc: "Which file transfer protocol to use. Either `winrm` or `smb`. Using `smb` is "\
|
29
|
-
"recommended for large file transfers." },
|
30
|
-
"host" => { type: String,
|
31
|
-
desc: "Host name." },
|
32
|
-
"interpreters" => { type: Hash,
|
33
|
-
desc: "A map of an extension name to the absolute path of an executable, "\
|
34
|
-
"enabling you to override the shebang defined in a task executable. The "\
|
35
|
-
"extension can optionally be specified with the `.` character (`.py` and "\
|
36
|
-
"`py` both map to a task executable `task.py`) and the extension is case "\
|
37
|
-
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
38
|
-
"Bolt Ruby interpreter by default." },
|
39
|
-
"password" => { type: String,
|
40
|
-
desc: "Login password. **Required unless using Kerberos.**" },
|
41
|
-
"port" => { type: Integer,
|
42
|
-
desc: "Connection port." },
|
43
|
-
"realm" => { type: String,
|
44
|
-
desc: "Kerberos realm (Active Directory domain) to authenticate against." },
|
45
|
-
"smb-port" => { type: Integer,
|
46
|
-
desc: "With file-protocol set to smb, this is the port to establish a "\
|
47
|
-
"connection on." },
|
48
|
-
"ssl" => { type: TrueClass,
|
49
|
-
desc: "When true, Bolt uses secure https connections for WinRM." },
|
50
|
-
"ssl-verify" => { type: TrueClass,
|
51
|
-
desc: "When true, verifies the targets certificate matches the cacert." },
|
52
|
-
"tmpdir" => { type: String,
|
53
|
-
desc: "The directory to upload and execute temporary files on the target." },
|
54
|
-
"user" => { type: String,
|
55
|
-
desc: "Login user. **Required unless using Kerberos.**" }
|
56
|
-
}.freeze
|
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
|
57
28
|
|
58
29
|
DEFAULTS = {
|
59
30
|
"basic-auth-only" => false,
|
data/lib/bolt/inventory/group.rb
CHANGED
@@ -16,7 +16,7 @@ module Bolt
|
|
16
16
|
DATA_KEYS = %w[config facts vars features plugin_hooks].freeze
|
17
17
|
TARGET_KEYS = DATA_KEYS + %w[name alias uri]
|
18
18
|
GROUP_KEYS = DATA_KEYS + %w[name groups targets]
|
19
|
-
CONFIG_KEYS = Bolt::Config::
|
19
|
+
CONFIG_KEYS = Bolt::Config::INVENTORY_OPTIONS.keys
|
20
20
|
|
21
21
|
def initialize(input, plugins)
|
22
22
|
@logger = Logging.logger[self]
|
@@ -78,20 +78,6 @@ module Bolt
|
|
78
78
|
target_array.first
|
79
79
|
end
|
80
80
|
|
81
|
-
def self.localhost_defaults(data)
|
82
|
-
defaults = {
|
83
|
-
'config' => {
|
84
|
-
'transport' => 'local',
|
85
|
-
'local' => { 'interpreters' => { '.rb' => RbConfig.ruby } }
|
86
|
-
},
|
87
|
-
'features' => ['puppet-agent']
|
88
|
-
}
|
89
|
-
data = Bolt::Util.deep_merge(defaults, data)
|
90
|
-
# If features is an empty array deep_merge won't add the puppet-agent
|
91
|
-
data['features'] += ['puppet-agent'] if data['features'].empty?
|
92
|
-
data
|
93
|
-
end
|
94
|
-
|
95
81
|
#### PRIVATE ####
|
96
82
|
def group_data_for(target_name)
|
97
83
|
@groups.group_collect(target_name)
|
@@ -30,6 +30,10 @@ module Bolt
|
|
30
30
|
@safe_name = @uri_obj.omit(:password).to_str.sub(%r{^//}, '')
|
31
31
|
end
|
32
32
|
|
33
|
+
if @name == 'localhost'
|
34
|
+
target_data = localhost_defaults(target_data)
|
35
|
+
end
|
36
|
+
|
33
37
|
@config = target_data['config'] || {}
|
34
38
|
@vars = target_data['vars'] || {}
|
35
39
|
@facts = target_data['facts'] || {}
|
@@ -45,6 +49,20 @@ module Bolt
|
|
45
49
|
validate
|
46
50
|
end
|
47
51
|
|
52
|
+
def localhost_defaults(data)
|
53
|
+
defaults = {
|
54
|
+
'config' => {
|
55
|
+
'transport' => 'local',
|
56
|
+
'local' => { 'interpreters' => { '.rb' => RbConfig.ruby } }
|
57
|
+
},
|
58
|
+
'features' => ['puppet-agent']
|
59
|
+
}
|
60
|
+
data = Bolt::Util.deep_merge(defaults, data)
|
61
|
+
# If features is an empty array deep_merge won't add the puppet-agent
|
62
|
+
data['features'] += ['puppet-agent'] if data['features'].empty?
|
63
|
+
data
|
64
|
+
end
|
65
|
+
|
48
66
|
# rubocop:disable Naming/AccessorMethodName
|
49
67
|
def set_resource(resource)
|
50
68
|
if (existing_resource = resources[resource.reference])
|
@@ -218,11 +236,6 @@ module Bolt
|
|
218
236
|
'target_alias' => []
|
219
237
|
}
|
220
238
|
|
221
|
-
# This should be handled by `get_targets`
|
222
|
-
if @name == 'localhost'
|
223
|
-
group_data = Bolt::Inventory::Inventory.localhost_defaults(group_data)
|
224
|
-
end
|
225
|
-
|
226
239
|
@group_cache = group_data
|
227
240
|
end
|
228
241
|
|
data/lib/bolt/pal.rb
CHANGED
@@ -137,7 +137,9 @@ module Bolt
|
|
137
137
|
# TODO: If we always call this inside a bolt_executor we can remove this here
|
138
138
|
setup
|
139
139
|
r = Puppet::Pal.in_tmp_environment('bolt', modulepath: @modulepath, facts: {}) do |pal|
|
140
|
-
|
140
|
+
# Only load the project if it a) exists, b) has a name it can be loaded with
|
141
|
+
bolt_project = @project if @project&.name
|
142
|
+
Puppet.override(bolt_project: bolt_project,
|
141
143
|
yaml_plan_instantiator: Bolt::PAL::YamlPlan::Loader) do
|
142
144
|
pal.with_script_compiler do |compiler|
|
143
145
|
alias_types(compiler)
|
data/lib/bolt/project.rb
CHANGED
@@ -9,8 +9,10 @@ module Bolt
|
|
9
9
|
BOLTDIR_NAME = 'Boltdir'
|
10
10
|
PROJECT_SETTINGS = {
|
11
11
|
"name" => "The name of the project",
|
12
|
-
"plans" => "An array of plan names to
|
13
|
-
|
12
|
+
"plans" => "An array of plan names to show, if they exist in the project."\
|
13
|
+
"These plans are included in `bolt plan show` output",
|
14
|
+
"tasks" => "An array of task names to show, if they exist in the project."\
|
15
|
+
"These tasks are included in `bolt task show` output"
|
14
16
|
}.freeze
|
15
17
|
|
16
18
|
attr_reader :path, :data, :config_file, :inventory_file, :modulepath, :hiera_config,
|
@@ -67,17 +69,17 @@ module Bolt
|
|
67
69
|
@resource_types = @path + '.resource_types'
|
68
70
|
@type = type
|
69
71
|
|
70
|
-
tc = Bolt::Config::
|
72
|
+
tc = Bolt::Config::INVENTORY_OPTIONS.keys & raw_data.keys
|
71
73
|
if tc.any?
|
72
74
|
msg = "Transport configuration isn't supported in bolt-project.yaml. Ignoring keys #{tc}"
|
73
75
|
@warnings << { msg: msg }
|
74
76
|
end
|
75
77
|
|
76
|
-
@data = raw_data.reject { |k, _| Bolt::Config::
|
78
|
+
@data = raw_data.reject { |k, _| Bolt::Config::INVENTORY_OPTIONS.include?(k) }
|
77
79
|
|
78
80
|
# Once bolt.yaml deprecation is removed, this attribute should be removed
|
79
81
|
# and replaced with .project_file in lib/bolt/config.rb
|
80
|
-
@config_file = if (Bolt::Config::
|
82
|
+
@config_file = if (Bolt::Config::BOLT_OPTIONS & @data.keys).any?
|
81
83
|
if (@path + 'bolt.yaml').file?
|
82
84
|
msg = "bolt-project.yaml contains valid config keys, bolt.yaml will be ignored"
|
83
85
|
@warnings << { msg: msg }
|
@@ -109,10 +111,7 @@ module Bolt
|
|
109
111
|
end
|
110
112
|
|
111
113
|
def name
|
112
|
-
|
113
|
-
dirname = @path.basename.to_s == 'Boltdir' ? @path.parent.basename.to_s : @path.basename.to_s
|
114
|
-
pname = @data['name'] || dirname
|
115
|
-
pname.include?('-') ? pname.split('-', 2)[1] : pname
|
114
|
+
@data['name']
|
116
115
|
end
|
117
116
|
|
118
117
|
def tasks
|
@@ -123,36 +122,20 @@ module Bolt
|
|
123
122
|
@data['plans']
|
124
123
|
end
|
125
124
|
|
126
|
-
def project_directory_name?(name)
|
127
|
-
# it must match an installed project name according to forge validator
|
128
|
-
name =~ /^[a-z][a-z0-9_]*$/
|
129
|
-
end
|
130
|
-
|
131
|
-
def project_namespaced_name?(name)
|
132
|
-
# it must match the full project name according to forge validator
|
133
|
-
name =~ /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/
|
134
|
-
end
|
135
|
-
|
136
125
|
def validate
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
Configure project name in <project_dir>/bolt-project.yaml
|
151
|
-
ERROR_STRING
|
152
|
-
# If the project name is the same as one of the built-in modules raise a warning
|
153
|
-
elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
|
154
|
-
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
|
155
|
-
"with a built-in Bolt module of the same name."
|
126
|
+
if name
|
127
|
+
name_regex = /^[a-z][a-z0-9_]*$/
|
128
|
+
if name !~ name_regex
|
129
|
+
raise Bolt::ValidationError, <<~ERROR_STRING
|
130
|
+
Invalid project name '#{name}' in bolt-project.yaml; project name must match #{name_regex.inspect}
|
131
|
+
ERROR_STRING
|
132
|
+
elsif Dir.children(Bolt::PAL::BOLTLIB_PATH).include?(name)
|
133
|
+
raise Bolt::ValidationError, "The project '#{name}' will not be loaded. The project name conflicts "\
|
134
|
+
"with a built-in Bolt module of the same name."
|
135
|
+
end
|
136
|
+
else
|
137
|
+
message = "No project name is specified in bolt-project.yaml. Project-level content will not be available."
|
138
|
+
@warnings << { msg: message }
|
156
139
|
end
|
157
140
|
|
158
141
|
%w[tasks plans].each do |conf|
|