bolt 0.23.0 → 0.24.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/apply_prep.rb +5 -2
- data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
- data/lib/bolt/applicator.rb +11 -8
- data/lib/bolt/boltdir.rb +13 -5
- data/lib/bolt/catalog.rb +22 -47
- data/lib/bolt/config.rb +1 -26
- data/lib/bolt/executor.rb +1 -1
- data/lib/bolt/outputter.rb +0 -9
- data/lib/bolt/outputter/human.rb +29 -14
- data/lib/bolt/outputter/json.rb +12 -1
- data/lib/bolt/pal.rb +12 -10
- data/lib/bolt/target.rb +0 -6
- data/lib/bolt/task.rb +53 -10
- data/lib/bolt/transport/base.rb +1 -6
- data/lib/bolt/transport/local.rb +11 -13
- data/lib/bolt/transport/local/shell.rb +2 -2
- data/lib/bolt/transport/ssh.rb +16 -11
- data/lib/bolt/transport/winrm.rb +8 -11
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_ext/schemas/task.json +12 -5
- data/libexec/apply_catalog.rb +3 -1
- data/libexec/bolt_catalog +4 -0
- data/vendored/puppet/lib/puppet.rb +2 -1
- data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
- data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
- data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
- data/vendored/puppet/lib/puppet/application/device.rb +0 -5
- data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
- data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
- data/vendored/puppet/lib/puppet/application_support.rb +1 -2
- data/vendored/puppet/lib/puppet/configurer.rb +34 -50
- data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
- data/vendored/puppet/lib/puppet/daemon.rb +1 -1
- data/vendored/puppet/lib/puppet/defaults.rb +40 -117
- data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
- data/vendored/puppet/lib/puppet/face/help.rb +21 -7
- data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
- data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
- data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
- data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
- data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
- data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
- data/vendored/puppet/lib/puppet/functions.rb +133 -0
- data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
- data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
- data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
- data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
- data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
- data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
- data/vendored/puppet/lib/puppet/graph.rb +0 -2
- data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
- data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
- data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
- data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
- data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
- data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
- data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
- data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
- data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
- data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
- data/vendored/puppet/lib/puppet/loaders.rb +1 -0
- data/vendored/puppet/lib/puppet/module/task.rb +198 -29
- data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
- data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
- data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
- data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
- data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
- data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
- data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
- data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
- data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
- data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
- data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
- data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
- data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
- data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
- data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
- data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
- data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
- data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
- data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
- data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
- data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
- data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
- data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
- data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
- data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
- data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
- data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
- data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
- data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
- data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
- data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
- data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
- data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
- data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
- data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
- data/vendored/puppet/lib/puppet/resource.rb +20 -3
- data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
- data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
- data/vendored/puppet/lib/puppet/settings.rb +1 -1
- data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
- data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
- data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
- data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
- data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
- data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
- data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
- data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
- data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
- data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
- data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
- data/vendored/puppet/lib/puppet/type/file.rb +3 -3
- data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
- data/vendored/puppet/lib/puppet/type/group.rb +3 -5
- data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
- data/vendored/puppet/lib/puppet/type/package.rb +2 -5
- data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
- data/vendored/puppet/lib/puppet/type/service.rb +3 -6
- data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
- data/vendored/puppet/lib/puppet/type/user.rb +13 -20
- data/vendored/puppet/lib/puppet/util.rb +8 -9
- data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
- data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
- data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
- data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
- data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
- data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
- data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
- data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
- data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
- data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
- data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
- data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
- data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
- data/vendored/puppet/lib/puppet/version.rb +1 -1
- data/vendored/puppet/lib/puppet_pal.rb +280 -24
- metadata +8 -38
- data/lib/bolt/catalog/compiler.rb +0 -48
- data/lib/bolt/catalog/loaders.rb +0 -19
- data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
- data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
- data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
- data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
- data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
- data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
- data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
- data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
- data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
- data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
- data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
- data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
- data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
- data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
- data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
- data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
- data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
- data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
- data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
- data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
- data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
- data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
- data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
- data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
- data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
- data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
- data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
- data/vendored/puppet/lib/puppet/type/cron.rb +0 -480
@@ -38,11 +38,9 @@ class Puppet::Node::Exec < Puppet::Indirector::Exec
|
|
38
38
|
# Turn our outputted objects into a Puppet::Node instance.
|
39
39
|
def create_node(name, result, facts = nil)
|
40
40
|
node = Puppet::Node.new(name)
|
41
|
-
set = false
|
42
41
|
[:parameters, :classes, :environment].each do |param|
|
43
42
|
if value = result[param]
|
44
43
|
node.send(param.to_s + "=", value)
|
45
|
-
set = true
|
46
44
|
end
|
47
45
|
end
|
48
46
|
|
@@ -52,7 +50,7 @@ class Puppet::Node::Exec < Puppet::Indirector::Exec
|
|
52
50
|
|
53
51
|
# Translate the yaml string into Ruby objects.
|
54
52
|
def translate(name, output)
|
55
|
-
|
53
|
+
Puppet::Util::Yaml.safe_load(output, [Symbol]).inject({}) do |hash, data|
|
56
54
|
case data[0]
|
57
55
|
when String
|
58
56
|
hash[data[0].intern] = data[1]
|
@@ -201,7 +201,7 @@ class Puppet::Indirector::Request
|
|
201
201
|
end
|
202
202
|
|
203
203
|
# ... Fall back onto the default server.
|
204
|
-
|
204
|
+
bound_server = Puppet.lookup(:server) do
|
205
205
|
if primary_server = Puppet.settings[:server_list][0]
|
206
206
|
primary_server[0]
|
207
207
|
else
|
@@ -12,13 +12,8 @@ class Puppet::Indirector::SslFile < Puppet::Indirector::Terminus
|
|
12
12
|
@file_setting = setting
|
13
13
|
end
|
14
14
|
|
15
|
-
# Specify where a specific ca file should be stored.
|
16
|
-
def self.store_ca_at(setting)
|
17
|
-
@ca_setting = setting
|
18
|
-
end
|
19
|
-
|
20
15
|
class << self
|
21
|
-
attr_reader :directory_setting, :file_setting
|
16
|
+
attr_reader :directory_setting, :file_setting
|
22
17
|
end
|
23
18
|
|
24
19
|
# The full path to where we should store our files.
|
@@ -33,19 +28,6 @@ class Puppet::Indirector::SslFile < Puppet::Indirector::Terminus
|
|
33
28
|
Puppet.settings[file_setting]
|
34
29
|
end
|
35
30
|
|
36
|
-
# The full path to a ca file we would be managing.
|
37
|
-
def self.ca_location
|
38
|
-
return nil unless ca_setting
|
39
|
-
Puppet.settings[ca_setting]
|
40
|
-
end
|
41
|
-
|
42
|
-
# We assume that all files named 'ca' are pointing to individual ca files,
|
43
|
-
# rather than normal host files. It's a bit hackish, but all the other
|
44
|
-
# solutions seemed even more hackish.
|
45
|
-
def ca?(name)
|
46
|
-
name == Puppet::SSL::Host.ca_name
|
47
|
-
end
|
48
|
-
|
49
31
|
def initialize
|
50
32
|
Puppet.settings.use(:main, :ssl)
|
51
33
|
|
@@ -58,9 +40,7 @@ class Puppet::Indirector::SslFile < Puppet::Indirector::Terminus
|
|
58
40
|
raise ArgumentError, _("invalid key")
|
59
41
|
end
|
60
42
|
|
61
|
-
if
|
62
|
-
ca_location
|
63
|
-
elsif collection_directory
|
43
|
+
if collection_directory
|
64
44
|
File.join(collection_directory, name.to_s + ".pem")
|
65
45
|
else
|
66
46
|
file_location
|
@@ -127,10 +107,6 @@ class Puppet::Indirector::SslFile < Puppet::Indirector::Terminus
|
|
127
107
|
self.class.file_location
|
128
108
|
end
|
129
109
|
|
130
|
-
def ca_location
|
131
|
-
self.class.ca_location
|
132
|
-
end
|
133
|
-
|
134
110
|
# A hack method to deal with files that exist with a different case.
|
135
111
|
# Just renames it; doesn't read it in or anything.
|
136
112
|
# LAK:NOTE This is a copy of the method in sslcertificates/support.rb,
|
@@ -164,25 +140,8 @@ class Puppet::Indirector::SslFile < Puppet::Indirector::Terminus
|
|
164
140
|
# * SSL::Key may be a .export(OpenSSL::Cipher::DES.new(:EDE3, :CBC), pass) or .to_pem
|
165
141
|
# * All other classes are translated to strings by calling .to_pem
|
166
142
|
|
167
|
-
|
168
|
-
# Puppet::SSL::Certificate by Puppet::SSL::Certificate::Ca, Puppet::SSL::Certificate::File
|
169
|
-
# -----BEGIN CERTIFICATE-----
|
170
|
-
# Puppet::SSL::Key by Puppet::SSL::Key::Ca, Puppet::SSL::Key::File
|
171
|
-
# -----BEGIN RSA PRIVATE KEY-----
|
172
|
-
if ca?(name) and ca_location
|
173
|
-
Puppet.settings.setting(self.class.ca_setting).open('w:ASCII') { |f| yield f }
|
174
|
-
# Serialization of:
|
175
|
-
# Puppet::SSL::CertificateRevocationList by Puppet::SSL::CertificateRevocationList::Ca, Puppet::SSL::CertificateRevocationList::File
|
176
|
-
# -----BEGIN X509 CRL-----
|
177
|
-
elsif file_location
|
143
|
+
if file_location
|
178
144
|
Puppet.settings.setting(self.class.file_setting).open('w:ASCII') { |f| yield f }
|
179
|
-
# Serialization of:
|
180
|
-
# Puppet::SSL::Certificate by Puppet::SSL::Certificate::Ca, Puppet::SSL::Certificate::File
|
181
|
-
# -----BEGIN CERTIFICATE-----
|
182
|
-
# Puppet::SSL::CertificateRequest by Puppet::SSL::CertificateRequest::Ca, Puppet::SSL::CertificateRequest::File
|
183
|
-
# -----BEGIN CERTIFICATE REQUEST-----
|
184
|
-
# Puppet::SSL::Key by Puppet::SSL::Key::Ca, Puppet::SSL::Key::File
|
185
|
-
# -----BEGIN RSA PRIVATE KEY-----
|
186
145
|
elsif setting = self.class.directory_setting
|
187
146
|
begin
|
188
147
|
Puppet.settings.setting(setting).open_file(path, 'w:ASCII') { |f| yield f }
|
@@ -9,7 +9,7 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
|
|
9
9
|
return nil unless Puppet::FileSystem.exist?(file)
|
10
10
|
|
11
11
|
begin
|
12
|
-
return
|
12
|
+
return load_file(file)
|
13
13
|
rescue Puppet::Util::Yaml::YamlLoadError => detail
|
14
14
|
raise Puppet::Error, _("Could not parse YAML data for %{indirection} %{request}: %{detail}") % { indirection: indirection.name, request: request.key, detail: detail }, detail.backtrace
|
15
15
|
end
|
@@ -51,13 +51,13 @@ class Puppet::Indirector::Yaml < Puppet::Indirector::Terminus
|
|
51
51
|
|
52
52
|
def search(request)
|
53
53
|
Dir.glob(path(request.key,'')).collect do |file|
|
54
|
-
|
54
|
+
load_file(file)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
protected
|
59
59
|
|
60
|
-
def
|
61
|
-
|
60
|
+
def load_file(file)
|
61
|
+
Puppet::Util::Yaml.safe_load_file(file, [model, Symbol])
|
62
62
|
end
|
63
63
|
end
|
@@ -23,10 +23,14 @@ class Puppet::InfoService::TaskInformationService
|
|
23
23
|
|
24
24
|
task = pup_module.tasks.find { |t| t.name == task_name }
|
25
25
|
if task.nil?
|
26
|
-
raise Puppet::Module::Task::TaskNotFound
|
27
|
-
{task_name: task_name, module_name: module_name}
|
26
|
+
raise Puppet::Module::Task::TaskNotFound.new(task_name, module_name)
|
28
27
|
end
|
29
28
|
|
30
|
-
|
29
|
+
begin
|
30
|
+
task.validate
|
31
|
+
{:metadata => task.metadata, :files => task.files}
|
32
|
+
rescue Puppet::Module::Task::Error => err
|
33
|
+
{ :metadata => nil, :files => [], :error => err.to_h }
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
@@ -13,6 +13,7 @@ module Puppet
|
|
13
13
|
require 'puppet/pops/loader/static_loader'
|
14
14
|
require 'puppet/pops/loader/runtime3_type_loader'
|
15
15
|
require 'puppet/pops/loader/ruby_function_instantiator'
|
16
|
+
require 'puppet/pops/loader/ruby_legacy_function_instantiator'
|
16
17
|
require 'puppet/pops/loader/ruby_data_type_instantiator'
|
17
18
|
require 'puppet/pops/loader/puppet_function_instantiator'
|
18
19
|
require 'puppet/pops/loader/type_definition_instantiator'
|
@@ -2,12 +2,50 @@ require 'puppet/util/logging'
|
|
2
2
|
|
3
3
|
class Puppet::Module
|
4
4
|
class Task
|
5
|
-
class Error < Puppet::Error
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
class Error < Puppet::Error
|
6
|
+
attr_accessor :kind, :details
|
7
|
+
def initialize(message, kind, details = nil)
|
8
|
+
super(message)
|
9
|
+
@details = details || {}
|
10
|
+
@kind = kind
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
{
|
15
|
+
msg: message,
|
16
|
+
kind: kind,
|
17
|
+
details: details
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class InvalidName < Error
|
23
|
+
def initialize(name)
|
24
|
+
msg = _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
|
25
|
+
super(msg, 'puppet.tasks/invalid-name')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class InvalidFile < Error
|
30
|
+
def initialize(msg)
|
31
|
+
super(msg, 'puppet.tasks/invalid-file')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class InvalidTask < Error
|
36
|
+
end
|
37
|
+
class InvalidMetadata < Error
|
38
|
+
end
|
39
|
+
class TaskNotFound < Error
|
40
|
+
def initialize(task_name, module_name)
|
41
|
+
msg = _("Task %{task_name} not found in module %{module_name}.") %
|
42
|
+
{task_name: task_name, module_name: module_name}
|
43
|
+
super(msg, 'puppet.tasks/task-not-found', { 'name' => task_name })
|
44
|
+
end
|
45
|
+
end
|
9
46
|
|
10
47
|
FORBIDDEN_EXTENSIONS = %w{.conf .md}
|
48
|
+
MOUNTS = %w[lib files tasks]
|
11
49
|
|
12
50
|
def self.is_task_name?(name)
|
13
51
|
return true if name =~ /^[a-z][a-z0-9_]*$/
|
@@ -24,6 +62,118 @@ class Puppet::Module
|
|
24
62
|
return true
|
25
63
|
end
|
26
64
|
|
65
|
+
def self.get_file_details(path, mod)
|
66
|
+
# This gets the path from the starting point onward
|
67
|
+
# For files this should be the file subpath from the metadata
|
68
|
+
# For directories it should be the directory subpath plus whatever we globbed
|
69
|
+
# Partition matches on the first instance it finds of the parameter
|
70
|
+
name = "#{mod.name}#{path.partition(mod.path).last}"
|
71
|
+
|
72
|
+
{ "name" => name, "path" => path }
|
73
|
+
end
|
74
|
+
private_class_method :get_file_details
|
75
|
+
|
76
|
+
# Find task's required lib files and retrieve paths for both 'files' and 'implementation:files' metadata keys
|
77
|
+
def self.find_extra_files(metadata, envname = nil)
|
78
|
+
return [] if metadata.nil?
|
79
|
+
|
80
|
+
files = metadata.fetch('files', []) +
|
81
|
+
metadata.fetch('implementations', []).flat_map { |impl| impl.fetch('files', []) }
|
82
|
+
|
83
|
+
files.uniq.flat_map do |file|
|
84
|
+
module_name, mount, endpath = file.split("/", 3)
|
85
|
+
# If there's a mount directory with no trailing slash this will be nil
|
86
|
+
# We want it to be empty to construct a path
|
87
|
+
endpath ||= ''
|
88
|
+
|
89
|
+
pup_module = Puppet::Module.find(module_name, envname)
|
90
|
+
if pup_module.nil?
|
91
|
+
msg = _("Could not find module %{module_name} containing task file %{filename}" %
|
92
|
+
{module_name: module_name, filename: endpath})
|
93
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
|
94
|
+
end
|
95
|
+
|
96
|
+
unless MOUNTS.include? mount
|
97
|
+
msg = _("Files must be saved in module directories that Puppet makes available via mount points: %{mounts}" %
|
98
|
+
{mounts: MOUNTS.join(', ')})
|
99
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
|
100
|
+
end
|
101
|
+
|
102
|
+
path = File.join(pup_module.path, mount, endpath)
|
103
|
+
unless File.absolute_path(path) == File.path(path).chomp('/')
|
104
|
+
msg = _("File pathnames cannot include relative paths")
|
105
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
|
106
|
+
end
|
107
|
+
|
108
|
+
unless File.exist?(path)
|
109
|
+
msg = _("Could not find %{path} on disk" % { path: path })
|
110
|
+
raise InvalidFile.new(msg)
|
111
|
+
end
|
112
|
+
|
113
|
+
last_char = file[-1] == '/'
|
114
|
+
if File.directory?(path)
|
115
|
+
unless last_char
|
116
|
+
msg = _("Directories specified in task metadata must include a trailing slash: %{dir}" % { dir: file } )
|
117
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
|
118
|
+
end
|
119
|
+
dir_files = Dir.glob("#{path}**/*").select { |f| File.file?(f) }
|
120
|
+
dir_files.map { |f| get_file_details(f, pup_module) }
|
121
|
+
else
|
122
|
+
if last_char
|
123
|
+
msg = _("Files specified in task metadata cannot include a trailing slash: %{file}" % { file: file } )
|
124
|
+
raise InvalidMetadata.new(msg, 'puppet.task/invalid-metadata')
|
125
|
+
end
|
126
|
+
get_file_details(path, pup_module)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
private_class_method :find_extra_files
|
131
|
+
|
132
|
+
# Executables list should contain the full path of all possible implementation files
|
133
|
+
def self.find_implementations(name, directory, metadata, executables)
|
134
|
+
basename = name.split('::')[1] || 'init'
|
135
|
+
# If 'implementations' is defined, it needs to mention at least one
|
136
|
+
# implementation, and everything it mentions must exist.
|
137
|
+
metadata ||= {}
|
138
|
+
if metadata.key?('implementations')
|
139
|
+
unless metadata['implementations'].is_a?(Array)
|
140
|
+
msg = _("Task metadata for task %{name} does not specify implementations as an array" % { name: name })
|
141
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/invalid-metadata')
|
142
|
+
end
|
143
|
+
|
144
|
+
implementations = metadata['implementations'].map do |impl|
|
145
|
+
path = executables.find { |real_impl| File.basename(real_impl) == impl['name'] }
|
146
|
+
unless path
|
147
|
+
msg = _("Task metadata for task %{name} specifies missing implementation %{implementation}" % { name: name, implementation: impl['name'] })
|
148
|
+
raise InvalidTask.new(msg, 'puppet.tasks/missing-implementation', { missing: [impl['name']] } )
|
149
|
+
end
|
150
|
+
{ "name" => impl['name'], "path" => path }
|
151
|
+
end
|
152
|
+
return implementations
|
153
|
+
end
|
154
|
+
|
155
|
+
# If implementations isn't defined, then we use executables matching the
|
156
|
+
# task name, and only one may exist.
|
157
|
+
implementations = executables.select { |impl| File.basename(impl, '.*') == basename }
|
158
|
+
if implementations.empty?
|
159
|
+
msg = _('No source besides task metadata was found in directory %{directory} for task %{name}') %
|
160
|
+
{ name: name, directory: directory }
|
161
|
+
raise InvalidTask.new(msg, 'puppet.tasks/no-implementation')
|
162
|
+
elsif implementations.length > 1
|
163
|
+
msg =_("Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them") %
|
164
|
+
{ name: name, directory: implementations[0] }
|
165
|
+
raise InvalidTask.new(msg, 'puppet.tasks/multiple-implementations')
|
166
|
+
end
|
167
|
+
|
168
|
+
[{ "name" => File.basename(implementations.first), "path" => implementations.first }]
|
169
|
+
end
|
170
|
+
private_class_method :find_implementations
|
171
|
+
|
172
|
+
def self.find_files(name, directory, metadata, executables, envname = nil)
|
173
|
+
# PXP agent relies on 'impls' (which is the task file) being first if there is no metadata
|
174
|
+
find_implementations(name, directory, metadata, executables) + find_extra_files(metadata, envname)
|
175
|
+
end
|
176
|
+
|
27
177
|
def self.is_tasks_metadata_filename?(name)
|
28
178
|
is_tasks_filename?(name) && name.end_with?('.json')
|
29
179
|
end
|
@@ -33,37 +183,54 @@ class Puppet::Module
|
|
33
183
|
end
|
34
184
|
|
35
185
|
def self.tasks_in_module(pup_module)
|
36
|
-
Dir.glob(File.join(pup_module.tasks_directory, '*'))
|
186
|
+
task_files = Dir.glob(File.join(pup_module.tasks_directory, '*'))
|
37
187
|
.keep_if { |f| is_tasks_filename?(f) }
|
38
|
-
.group_by { |f| task_name_from_path(f) }
|
39
|
-
.map { |task, files| new_with_files(pup_module, task, files) }
|
40
|
-
end
|
41
188
|
|
42
|
-
|
189
|
+
module_executables = task_files.reject(&method(:is_tasks_metadata_filename?)).map.to_a
|
43
190
|
|
44
|
-
|
45
|
-
|
46
|
-
|
191
|
+
tasks = task_files.group_by { |f| task_name_from_path(f) }
|
192
|
+
|
193
|
+
tasks.map do |task, executables|
|
194
|
+
new_with_files(pup_module, task, executables, module_executables)
|
47
195
|
end
|
196
|
+
end
|
48
197
|
|
49
|
-
|
50
|
-
all_files.each do |f|
|
51
|
-
if !f.start_with?(pup_module.tasks_directory)
|
52
|
-
msg = _("The file '%{path}' is not located in the %{module_name} module's tasks directory") %
|
53
|
-
{path: f.to_s, module_name: pup_module.name}
|
198
|
+
attr_reader :name, :module, :metadata_file, :metadata
|
54
199
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
200
|
+
# file paths must be relative to the modules task directory
|
201
|
+
def initialize(pup_module, task_name, module_executables, metadata_file = nil)
|
202
|
+
if !Puppet::Module::Task.is_task_name?(task_name)
|
203
|
+
raise InvalidName, _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
|
59
204
|
end
|
60
205
|
|
61
206
|
name = task_name == "init" ? pup_module.name : "#{pup_module.name}::#{task_name}"
|
62
207
|
|
63
208
|
@module = pup_module
|
64
209
|
@name = name
|
65
|
-
@metadata_file = metadata_file
|
66
|
-
@
|
210
|
+
@metadata_file = metadata_file
|
211
|
+
@module_executables = module_executables || []
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.read_metadata(file)
|
215
|
+
Puppet::Util::Json.load(Puppet::FileSystem.read(file, :encoding => 'utf-8')) if file
|
216
|
+
rescue SystemCallError, IOError => err
|
217
|
+
msg = _("Error reading metadata: %{message}" % {message: err.message})
|
218
|
+
raise InvalidMetadata.new(msg, 'puppet.tasks/unreadable-metadata')
|
219
|
+
rescue Puppet::Util::Json::ParseError => err
|
220
|
+
raise InvalidMetadata.new(err.message, 'puppet.tasks/unparseable-metadata')
|
221
|
+
end
|
222
|
+
|
223
|
+
def metadata
|
224
|
+
@metadata ||= self.class.read_metadata(@metadata_file)
|
225
|
+
end
|
226
|
+
|
227
|
+
def files
|
228
|
+
@files ||= self.class.find_files(@name, @module.tasks_directory, metadata, @module_executables, environment_name)
|
229
|
+
end
|
230
|
+
|
231
|
+
def validate
|
232
|
+
files
|
233
|
+
true
|
67
234
|
end
|
68
235
|
|
69
236
|
def ==(other)
|
@@ -71,16 +238,18 @@ class Puppet::Module
|
|
71
238
|
self.module == other.module
|
72
239
|
end
|
73
240
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
241
|
+
def environment_name
|
242
|
+
@module.environment.respond_to?(:name) ? @module.environment.name : 'production'
|
243
|
+
end
|
244
|
+
private :environment_name
|
78
245
|
|
79
|
-
|
80
|
-
|
246
|
+
def self.new_with_files(pup_module, name, task_files, module_executables)
|
247
|
+
metadata_file = task_files.find { |f| is_tasks_metadata_filename?(f) }
|
248
|
+
Puppet::Module::Task.new(pup_module, name, module_executables, metadata_file)
|
81
249
|
end
|
82
250
|
private_class_method :new_with_files
|
83
251
|
|
252
|
+
# Abstracted here so we can add support for subdirectories later
|
84
253
|
def self.task_name_from_path(path)
|
85
254
|
return File.basename(path, '.*')
|
86
255
|
end
|