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.

Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
  5. data/lib/bolt/applicator.rb +11 -8
  6. data/lib/bolt/boltdir.rb +13 -5
  7. data/lib/bolt/catalog.rb +22 -47
  8. data/lib/bolt/config.rb +1 -26
  9. data/lib/bolt/executor.rb +1 -1
  10. data/lib/bolt/outputter.rb +0 -9
  11. data/lib/bolt/outputter/human.rb +29 -14
  12. data/lib/bolt/outputter/json.rb +12 -1
  13. data/lib/bolt/pal.rb +12 -10
  14. data/lib/bolt/target.rb +0 -6
  15. data/lib/bolt/task.rb +53 -10
  16. data/lib/bolt/transport/base.rb +1 -6
  17. data/lib/bolt/transport/local.rb +11 -13
  18. data/lib/bolt/transport/local/shell.rb +2 -2
  19. data/lib/bolt/transport/ssh.rb +16 -11
  20. data/lib/bolt/transport/winrm.rb +8 -11
  21. data/lib/bolt/version.rb +1 -1
  22. data/lib/bolt_ext/schemas/task.json +12 -5
  23. data/libexec/apply_catalog.rb +3 -1
  24. data/libexec/bolt_catalog +4 -0
  25. data/vendored/puppet/lib/puppet.rb +2 -1
  26. data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
  27. data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
  28. data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
  29. data/vendored/puppet/lib/puppet/application/device.rb +0 -5
  30. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
  31. data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
  32. data/vendored/puppet/lib/puppet/application_support.rb +1 -2
  33. data/vendored/puppet/lib/puppet/configurer.rb +34 -50
  34. data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
  35. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  36. data/vendored/puppet/lib/puppet/daemon.rb +1 -1
  37. data/vendored/puppet/lib/puppet/defaults.rb +40 -117
  38. data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
  39. data/vendored/puppet/lib/puppet/face/help.rb +21 -7
  40. data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
  41. data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
  42. data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
  43. data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
  44. data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
  45. data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
  46. data/vendored/puppet/lib/puppet/functions.rb +133 -0
  47. data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
  48. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
  49. data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
  50. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  51. data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
  52. data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
  53. data/vendored/puppet/lib/puppet/graph.rb +0 -2
  54. data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
  55. data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
  56. data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
  57. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
  58. data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
  59. data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
  60. data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
  61. data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
  62. data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
  63. data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
  64. data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
  65. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  66. data/vendored/puppet/lib/puppet/module/task.rb +198 -29
  67. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  68. data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
  69. data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
  70. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
  71. data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
  72. data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
  73. data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
  74. data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
  75. data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
  76. data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
  77. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
  78. data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
  79. data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
  80. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
  81. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  82. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
  83. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
  84. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
  85. data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
  86. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
  87. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
  88. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
  89. data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
  90. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
  91. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  92. data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
  93. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  94. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
  95. data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
  96. data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
  97. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
  98. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
  100. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  101. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
  102. data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
  103. data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
  104. data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
  105. data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
  106. data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
  107. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  108. data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
  109. data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
  110. data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
  111. data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
  112. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
  113. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  114. data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
  115. data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
  116. data/vendored/puppet/lib/puppet/resource.rb +20 -3
  117. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
  118. data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
  119. data/vendored/puppet/lib/puppet/settings.rb +1 -1
  120. data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
  121. data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
  122. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
  123. data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  124. data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
  125. data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
  126. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  127. data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
  128. data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
  129. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  130. data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
  131. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  132. data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
  133. data/vendored/puppet/lib/puppet/type/group.rb +3 -5
  134. data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
  135. data/vendored/puppet/lib/puppet/type/package.rb +2 -5
  136. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  137. data/vendored/puppet/lib/puppet/type/service.rb +3 -6
  138. data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
  139. data/vendored/puppet/lib/puppet/type/user.rb +13 -20
  140. data/vendored/puppet/lib/puppet/util.rb +8 -9
  141. data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
  142. data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
  143. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  144. data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
  145. data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
  146. data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
  147. data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
  148. data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  150. data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
  151. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
  152. data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
  153. data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
  154. data/vendored/puppet/lib/puppet/version.rb +1 -1
  155. data/vendored/puppet/lib/puppet_pal.rb +280 -24
  156. metadata +8 -38
  157. data/lib/bolt/catalog/compiler.rb +0 -48
  158. data/lib/bolt/catalog/loaders.rb +0 -19
  159. data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
  160. data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
  161. data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
  162. data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
  163. data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
  164. data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
  165. data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
  166. data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
  167. data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
  168. data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
  169. data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
  170. data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
  171. data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
  172. data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
  173. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
  174. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
  175. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
  176. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
  177. data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
  178. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
  179. data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
  180. data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
  181. data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
  182. data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
  183. data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
  184. data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
  185. data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
  186. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
  187. data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
  188. data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
  189. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
  190. data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
  191. data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
  192. 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
- YAML.load(output).inject({}) do |hash, data|
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]
@@ -4,10 +4,4 @@ require 'puppet/indirector/yaml'
4
4
  class Puppet::Node::Yaml < Puppet::Indirector::Yaml
5
5
  desc "Store node information as flat files, serialized using YAML,
6
6
  or deserialize stored YAML nodes."
7
-
8
- protected
9
-
10
- def fix(object)
11
- object
12
- end
13
7
  end
@@ -201,7 +201,7 @@ class Puppet::Indirector::Request
201
201
  end
202
202
 
203
203
  # ... Fall back onto the default server.
204
- bound_server = Puppet.lookup(:server) do
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, :ca_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 ca?(name) and ca_location
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
- # Serialization of:
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 fix(Puppet::Util::Yaml.load_file(file))
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
- fix(Puppet::Util::Yaml.load_file(file))
54
+ load_file(file)
55
55
  end
56
56
  end
57
57
 
58
58
  protected
59
59
 
60
- def fix(object)
61
- object
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, _("Task %{task_name} not found in module %{module_name}.") %
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
- {:metadata_file => task.metadata_file, :files => task.files}
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; end
6
- class InvalidName < Error; end
7
- class InvalidFile < Error; end
8
- class TaskNotFound < Error; end
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
- attr_reader :name, :module, :metadata_file, :files
189
+ module_executables = task_files.reject(&method(:is_tasks_metadata_filename?)).map.to_a
43
190
 
44
- def initialize(pup_module, task_name, files, metadata_file = nil)
45
- if !Puppet::Module::Task.is_task_name?(task_name)
46
- raise InvalidName, _("Task names must start with a lowercase letter and be composed of only lowercase letters, numbers, and underscores")
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
- all_files = metadata_file.nil? ? files : files + [metadata_file]
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
- # we can include some extra context for the log message:
56
- Puppet.err(msg + " (#{pup_module.tasks_directory})")
57
- raise InvalidFile, msg
58
- end
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 if metadata_file
66
- @files = files
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 self.new_with_files(pup_module, name, tasks_files)
75
- files = tasks_files.map do |filename|
76
- File.join(pup_module.tasks_directory, File.basename(filename))
77
- end
241
+ def environment_name
242
+ @module.environment.respond_to?(:name) ? @module.environment.name : 'production'
243
+ end
244
+ private :environment_name
78
245
 
79
- metadata_files, exe_files = files.partition { |f| is_tasks_metadata_filename?(f) }
80
- Puppet::Module::Task.new(pup_module, name, exe_files, metadata_files.first)
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