puppet 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +8 -35
  3. data/ext/debian/puppet.default +0 -5
  4. data/ext/debian/puppet.init +1 -15
  5. data/lib/hiera/puppet_function.rb +15 -4
  6. data/lib/puppet/application/agent.rb +5 -0
  7. data/lib/puppet/application/apply.rb +23 -2
  8. data/lib/puppet/application/device.rb +8 -3
  9. data/lib/puppet/application/master.rb +16 -5
  10. data/lib/puppet/configurer.rb +7 -5
  11. data/lib/puppet/defaults.rb +18 -0
  12. data/lib/puppet/environments.rb +1 -1
  13. data/lib/puppet/error.rb +27 -1
  14. data/lib/puppet/file_serving/metadata.rb +13 -8
  15. data/lib/puppet/file_serving/terminus_helper.rb +7 -8
  16. data/lib/puppet/file_system.rb +13 -0
  17. data/lib/puppet/file_system/file_impl.rb +4 -0
  18. data/lib/puppet/file_system/memory_impl.rb +4 -0
  19. data/lib/puppet/file_system/windows.rb +8 -0
  20. data/lib/puppet/functions.rb +33 -3
  21. data/lib/puppet/functions/defined.rb +130 -0
  22. data/lib/puppet/functions/regsubst.rb +1 -1
  23. data/lib/puppet/functions/split.rb +1 -1
  24. data/lib/puppet/indirector/catalog/compiler.rb +1 -1
  25. data/lib/puppet/indirector/facts/facter.rb +11 -0
  26. data/lib/puppet/loaders.rb +1 -0
  27. data/lib/puppet/node.rb +17 -1
  28. data/lib/puppet/node/environment.rb +4 -0
  29. data/lib/puppet/parser/ast/pops_bridge.rb +4 -0
  30. data/lib/puppet/parser/compiler.rb +9 -0
  31. data/lib/puppet/parser/functions/defined.rb +25 -1
  32. data/lib/puppet/parser/functions/file.rb +3 -1
  33. data/lib/puppet/parser/scope.rb +11 -2
  34. data/lib/puppet/parser/templatewrapper.rb +2 -1
  35. data/lib/puppet/pops.rb +4 -0
  36. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  37. data/lib/puppet/pops/evaluator/closure.rb +28 -2
  38. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  39. data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +4 -0
  40. data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +4 -0
  41. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  42. data/lib/puppet/pops/evaluator/epp_evaluator.rb +7 -2
  43. data/lib/puppet/pops/evaluator/evaluator_impl.rb +48 -14
  44. data/lib/puppet/pops/evaluator/runtime3_support.rb +10 -5
  45. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  46. data/lib/puppet/pops/functions/dispatcher.rb +7 -1
  47. data/lib/puppet/pops/issue_reporter.rb +42 -16
  48. data/lib/puppet/pops/issues.rb +116 -2
  49. data/lib/puppet/pops/loader/loader.rb +11 -0
  50. data/lib/puppet/pops/loader/loader_paths.rb +67 -6
  51. data/lib/puppet/pops/loader/module_loaders.rb +19 -8
  52. data/lib/puppet/pops/loader/puppet_function_instantiator.rb +78 -0
  53. data/lib/puppet/pops/loaders.rb +6 -4
  54. data/lib/puppet/pops/migration/migration_checker.rb +54 -0
  55. data/lib/puppet/pops/model/factory.rb +5 -1
  56. data/lib/puppet/pops/model/model_label_provider.rb +2 -0
  57. data/lib/puppet/pops/model/model_meta.rb +5 -1
  58. data/lib/puppet/pops/parser/egrammar.ra +9 -10
  59. data/lib/puppet/pops/parser/eparser.rb +1061 -1047
  60. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  61. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  62. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  63. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  64. data/lib/puppet/pops/parser/lexer2.rb +29 -12
  65. data/lib/puppet/pops/parser/lexer_support.rb +52 -23
  66. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  67. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  68. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  69. data/lib/puppet/pops/types/type_factory.rb +66 -13
  70. data/lib/puppet/pops/types/type_parser.rb +22 -13
  71. data/lib/puppet/pops/types/types.rb +23 -4
  72. data/lib/puppet/pops/types/types_meta.rb +13 -2
  73. data/lib/puppet/pops/validation.rb +25 -2
  74. data/lib/puppet/pops/validation/checker4_0.rb +63 -31
  75. data/lib/puppet/provider/group/windows_adsi.rb +8 -4
  76. data/lib/puppet/provider/mount/parsed.rb +145 -2
  77. data/lib/puppet/provider/package/apt.rb +1 -1
  78. data/lib/puppet/provider/package/pip.rb +11 -2
  79. data/lib/puppet/provider/package/pkgng.rb +134 -0
  80. data/lib/puppet/provider/package/portage.rb +1 -1
  81. data/lib/puppet/provider/package/ports.rb +0 -3
  82. data/lib/puppet/provider/package/windows/exe_package.rb +0 -1
  83. data/lib/puppet/provider/package/windows/msi_package.rb +0 -1
  84. data/lib/puppet/provider/package/zypper.rb +50 -15
  85. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +32 -7
  86. data/lib/puppet/provider/service/debian.rb +1 -1
  87. data/lib/puppet/provider/service/init.rb +7 -0
  88. data/lib/puppet/provider/user/openbsd.rb +1 -0
  89. data/lib/puppet/provider/user/windows_adsi.rb +45 -2
  90. data/lib/puppet/reference/indirection.rb +1 -1
  91. data/lib/puppet/resource.rb +1 -1
  92. data/lib/puppet/resource/catalog.rb +0 -4
  93. data/lib/puppet/settings.rb +19 -0
  94. data/lib/puppet/type/file.rb +1 -0
  95. data/lib/puppet/type/file/ensure.rb +1 -1
  96. data/lib/puppet/type/mount.rb +9 -1
  97. data/lib/puppet/type/scheduled_task.rb +13 -0
  98. data/lib/puppet/type/tidy.rb +3 -1
  99. data/lib/puppet/type/user.rb +32 -0
  100. data/lib/puppet/type/yumrepo.rb +5 -5
  101. data/lib/puppet/util/log.rb +50 -8
  102. data/lib/puppet/util/log/destinations.rb +23 -2
  103. data/lib/puppet/util/logging.rb +37 -1
  104. data/lib/puppet/util/run_mode.rb +1 -14
  105. data/lib/puppet/util/windows/adsi.rb +130 -58
  106. data/lib/puppet/version.rb +1 -1
  107. data/man/man5/puppet.conf.5 +48 -6
  108. data/man/man8/extlookup2hiera.8 +1 -1
  109. data/man/man8/puppet-agent.8 +4 -1
  110. data/man/man8/puppet-apply.8 +4 -1
  111. data/man/man8/puppet-ca.8 +1 -1
  112. data/man/man8/puppet-catalog.8 +1 -1
  113. data/man/man8/puppet-cert.8 +1 -1
  114. data/man/man8/puppet-certificate.8 +1 -1
  115. data/man/man8/puppet-certificate_request.8 +1 -1
  116. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  117. data/man/man8/puppet-config.8 +1 -1
  118. data/man/man8/puppet-describe.8 +1 -1
  119. data/man/man8/puppet-device.8 +6 -3
  120. data/man/man8/puppet-doc.8 +1 -1
  121. data/man/man8/puppet-epp.8 +1 -1
  122. data/man/man8/puppet-facts.8 +1 -1
  123. data/man/man8/puppet-file.8 +1 -1
  124. data/man/man8/puppet-filebucket.8 +1 -1
  125. data/man/man8/puppet-help.8 +1 -1
  126. data/man/man8/puppet-inspect.8 +1 -1
  127. data/man/man8/puppet-key.8 +1 -1
  128. data/man/man8/puppet-man.8 +1 -1
  129. data/man/man8/puppet-master.8 +4 -1
  130. data/man/man8/puppet-module.8 +1 -1
  131. data/man/man8/puppet-node.8 +1 -1
  132. data/man/man8/puppet-parser.8 +1 -1
  133. data/man/man8/puppet-plugin.8 +1 -1
  134. data/man/man8/puppet-report.8 +1 -1
  135. data/man/man8/puppet-resource.8 +1 -1
  136. data/man/man8/puppet-resource_type.8 +1 -1
  137. data/man/man8/puppet-status.8 +1 -1
  138. data/man/man8/puppet.8 +1 -1
  139. data/spec/fixtures/unit/data_providers/environments/production/lib/puppet/functions/environment/data.rb +3 -1
  140. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/functions/data.pp +6 -0
  141. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/lib/puppet/bindings/xyz/default.rb +9 -0
  142. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/manifests/init.pp +9 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcalled.pp +3 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller.pp +3 -0
  145. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller4.pp +3 -0
  146. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/callingpuppet.rb +5 -0
  147. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/functions/hello.pp +3 -0
  148. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/manifests/init.pp +3 -0
  149. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/metadata.json +10 -0
  150. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/hello.pp +3 -0
  151. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/subspace/hello.pp +3 -0
  152. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +1 -10
  153. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  154. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  155. data/spec/fixtures/unit/provider/package/pkgng/pkg.info +8 -0
  156. data/spec/fixtures/unit/provider/package/pkgng/pkg.query +1 -0
  157. data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +1 -0
  158. data/spec/fixtures/unit/provider/package/pkgng/pkg.version +3 -0
  159. data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-empty.out +3 -0
  160. data/spec/integration/application/apply_spec.rb +49 -0
  161. data/spec/integration/faces/plugin_spec.rb +0 -4
  162. data/spec/integration/indirector/facts/facter_spec.rb +59 -0
  163. data/spec/integration/parser/compiler_spec.rb +850 -0
  164. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  165. data/spec/integration/parser/scope_spec.rb +26 -5
  166. data/spec/integration/transaction_spec.rb +1 -1
  167. data/spec/integration/type/file_spec.rb +318 -41
  168. data/spec/integration/util/windows/security_spec.rb +14 -5
  169. data/spec/lib/matchers/resource.rb +22 -1
  170. data/spec/lib/puppet_spec/matchers.rb +6 -4
  171. data/spec/unit/application/master_spec.rb +33 -7
  172. data/spec/unit/data_providers/function_data_provider_spec.rb +10 -1
  173. data/spec/unit/file_serving/metadata_spec.rb +1 -1
  174. data/spec/unit/file_serving/terminus_helper_spec.rb +2 -3
  175. data/spec/unit/file_system_spec.rb +38 -0
  176. data/spec/unit/functions/defined_spec.rb +289 -0
  177. data/spec/unit/functions/hiera_spec.rb +8 -6
  178. data/spec/unit/functions/regsubst_spec.rb +4 -0
  179. data/spec/unit/functions/split_spec.rb +8 -0
  180. data/spec/unit/functions4_spec.rb +97 -2
  181. data/spec/unit/indirector/facts/facter_spec.rb +7 -0
  182. data/spec/unit/node_spec.rb +6 -0
  183. data/spec/unit/parser/functions/file_spec.rb +7 -1
  184. data/spec/unit/parser/functions/template_spec.rb +1 -1
  185. data/spec/unit/parser/scope_spec.rb +2 -2
  186. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  187. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  188. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +84 -18
  189. data/spec/unit/pops/evaluator/variables_spec.rb +1 -1
  190. data/spec/unit/pops/issues_spec.rb +16 -16
  191. data/spec/unit/pops/loaders/loaders_spec.rb +106 -48
  192. data/spec/unit/pops/migration_spec.rb +53 -0
  193. data/spec/unit/pops/parser/lexer2_spec.rb +142 -1
  194. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  195. data/spec/unit/pops/types/type_calculator_spec.rb +205 -12
  196. data/spec/unit/pops/validation_spec.rb +66 -0
  197. data/spec/unit/pops/validator/validator_spec.rb +1 -1
  198. data/spec/unit/provider/group/windows_adsi_spec.rb +57 -9
  199. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  200. data/spec/unit/provider/package/apt_spec.rb +5 -0
  201. data/spec/unit/provider/package/pip_spec.rb +9 -0
  202. data/spec/unit/provider/package/pkgng_spec.rb +172 -0
  203. data/spec/unit/provider/package/windows/exe_package_spec.rb +0 -1
  204. data/spec/unit/provider/package/windows/msi_package_spec.rb +0 -1
  205. data/spec/unit/provider/package/zypper_spec.rb +50 -19
  206. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  207. data/spec/unit/provider/service/base_spec.rb +38 -27
  208. data/spec/unit/provider/service/debian_spec.rb +8 -0
  209. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  210. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  211. data/spec/unit/provider/service/init_spec.rb +18 -0
  212. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  213. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  214. data/spec/unit/provider/user/windows_adsi_spec.rb +134 -5
  215. data/spec/unit/settings_spec.rb +11 -0
  216. data/spec/unit/util/log_spec.rb +113 -0
  217. data/spec/unit/util/windows/adsi_spec.rb +135 -41
  218. data/spec/unit/util/windows/sid_spec.rb +0 -10
  219. metadata +48 -2
@@ -13,6 +13,7 @@ class Puppet::Pops::Types::TypeParser
13
13
  def initialize
14
14
  @parser = Puppet::Pops::Parser::Parser.new()
15
15
  @type_transformer = Puppet::Pops::Visitor.new(nil, "interpret", 0, 0)
16
+ @undef_t = TYPES.undef
16
17
  end
17
18
 
18
19
  # Produces a *puppet type* based on the given string.
@@ -163,6 +164,9 @@ class Puppet::Pops::Types::TypeParser
163
164
  when "undef"
164
165
  TYPES.undef()
165
166
 
167
+ when "notundef"
168
+ TYPES.not_undef()
169
+
166
170
  when "default"
167
171
  TYPES.default()
168
172
 
@@ -344,8 +348,9 @@ class Puppet::Pops::Types::TypeParser
344
348
  when "struct"
345
349
  # 1..m parameters being types (last two optionally integer or literal default
346
350
  raise_invalid_parameters_error("Struct", "1", parameters.size) unless parameters.size == 1
347
- assert_struct_parameter(parameters[0])
348
- TYPES.struct(parameters[0])
351
+ h = parameters[0]
352
+ raise_invalid_type_specification_error unless h.is_a?(Hash)
353
+ TYPES.struct(h)
349
354
 
350
355
  when "integer"
351
356
  if parameters.size == 1
@@ -400,12 +405,25 @@ class Puppet::Pops::Types::TypeParser
400
405
  if parameters.size != 1
401
406
  raise_invalid_parameters_error("Optional", 1, parameters.size)
402
407
  end
403
- assert_type(parameters[0])
404
- TYPES.optional(parameters[0])
408
+ param = parameters[0]
409
+ assert_type(param) unless param.is_a?(String)
410
+ TYPES.optional(param)
405
411
 
406
412
  when "any", "data", "catalogentry", "boolean", "scalar", "undef", "numeric", "default"
407
413
  raise_unparameterized_type_error(parameterized_ast.left_expr)
408
414
 
415
+ when "notundef"
416
+ case parameters.size
417
+ when 0
418
+ TYPES.not_undef
419
+ when 1
420
+ param = parameters[0]
421
+ assert_type(param) unless param.is_a?(String)
422
+ TYPES.not_undef(param)
423
+ else
424
+ raise_invalid_parameters_error("NotUndef", "0 to 1", parameters.size)
425
+ end
426
+
409
427
  when "type"
410
428
  if parameters.size != 1
411
429
  raise_invalid_parameters_error("Type", 1, parameters.size)
@@ -438,15 +456,6 @@ class Puppet::Pops::Types::TypeParser
438
456
  raise_invalid_type_specification_error unless TYPES.is_range_parameter?(t)
439
457
  end
440
458
 
441
- def assert_struct_parameter(h)
442
- raise_invalid_type_specification_error unless h.is_a?(Hash)
443
- h.each do |k,v|
444
- # TODO: Should have stricter name rule
445
- raise_invalid_type_specification_error unless k.is_a?(String) && !k.empty?
446
- assert_type(v)
447
- end
448
- end
449
-
450
459
  def raise_invalid_type_specification_error
451
460
  raise Puppet::ParseError,
452
461
  "The expression <#{@string}> is not a valid type specification."
@@ -42,6 +42,18 @@ module Puppet::Pops
42
42
  end
43
43
  end
44
44
 
45
+ class PNotUndefType < PAnyType
46
+ module ClassModule
47
+ def hash
48
+ [self.class, type].hash
49
+ end
50
+
51
+ def ==(o)
52
+ self.class == o.class && type == o.type
53
+ end
54
+ end
55
+ end
56
+
45
57
  class PType < PAnyType
46
58
  module ClassModule
47
59
  def hash
@@ -162,7 +174,8 @@ module Puppet::Pops
162
174
  class PRegexpType < PScalarType
163
175
  module ClassModule
164
176
  def regexp_derived
165
- @_regexp = Regexp.new(pattern) unless @_regexp && @_regexp.source == pattern
177
+ pattern_or_blank = pattern || ''
178
+ @_regexp = Regexp.new(pattern_or_blank) unless @_regexp && @_regexp.source == pattern_or_blank
166
179
  @_regexp
167
180
  end
168
181
 
@@ -216,11 +229,17 @@ module Puppet::Pops
216
229
  class PStructElement < TypeModelObject
217
230
  module ClassModule
218
231
  def hash
219
- [self.class, type, name].hash
232
+ [self.class, value_type, key_type].hash
233
+ end
234
+
235
+ def name
236
+ k = key_type
237
+ k = k.optional_type if k.is_a?(POptionalType)
238
+ k.values[0]
220
239
  end
221
240
 
222
241
  def ==(o)
223
- self.class == o.class && type == o.type && name == o.name
242
+ self.class == o.class && value_type == o.value_type && key_type == o.key_type
224
243
  end
225
244
  end
226
245
  end
@@ -229,7 +248,7 @@ module Puppet::Pops
229
248
  class PStructType < PAnyType
230
249
  module ClassModule
231
250
  def hashed_elements_derived
232
- @_hashed ||= elements.reduce({}) {|memo, e| memo[e.name] = e.type; memo }
251
+ @_hashed ||= elements.reduce({}) {|memo, e| memo[e.name] = e; memo }
233
252
  @_hashed
234
253
  end
235
254
 
@@ -27,6 +27,15 @@ module Puppet::Pops::Types
27
27
  class PAnyType < TypeModelObject
28
28
  end
29
29
 
30
+ # A type that is assignable from the same types as its contained `type` except the
31
+ # types assignable from {Puppet::Pops::Types::PUndefType}
32
+ #
33
+ # @api public
34
+ #
35
+ class PNotUndefType < PAnyType
36
+ contains_one_uni 'type', PAnyType
37
+ end
38
+
30
39
  # The type of types.
31
40
  # @api public
32
41
  #
@@ -135,8 +144,10 @@ module Puppet::Pops::Types
135
144
  # @api public
136
145
  #
137
146
  class PStructElement < TypeModelObject
138
- has_attr 'name', String, :lowerBound => 1
139
- contains_one_uni 'type', PAnyType
147
+ # key_type must be either String[1] or Optional[String[1]] and the String[1] must
148
+ # have a values collection with exactly one element
149
+ contains_one_uni 'key_type', PAnyType, :lowerBound => 1
150
+ contains_one_uni 'value_type', PAnyType
140
151
  end
141
152
 
142
153
  # @api public
@@ -93,11 +93,12 @@ module Puppet::Pops::Validation
93
93
  @@severity_hash = {:ignore => true, :warning => true, :error => true, :deprecation => true }
94
94
 
95
95
  # Creates a new instance where all issues are diagnosed as :error unless overridden.
96
+ # @param [Symbol] specifies default severity if :error is not wanted as the default
96
97
  # @api public
97
98
  #
98
- def initialize
99
+ def initialize(default_severity = :error)
99
100
  # If diagnose is not set, the default is returned by the block
100
- @severities = Hash.new :error
101
+ @severities = Hash.new default_severity
101
102
  end
102
103
 
103
104
  # Returns the severity of the given issue.
@@ -227,6 +228,28 @@ module Puppet::Pops::Validation
227
228
  # debugging or similar - this to catch internal problems reported as higher level issues.
228
229
  @exception = exception
229
230
  end
231
+
232
+ # Two diagnostics are considered equal if the have the same issue, location and severity
233
+ # (arguments and exception are ignored)
234
+ #
235
+ def ==(o)
236
+ self.class == o.class &&
237
+ same_position?(o) &&
238
+ issue.issue_code == o.issue.issue_code &&
239
+ file == o.file &&
240
+ severity == o.severity
241
+ end
242
+ alias eql? ==
243
+
244
+ # Position is equal if the diagnostic is not located or if referring to the same offset
245
+ def same_position?(o)
246
+ source_pos.nil? && o.source_pos.nil? || source_pos.offset == o.source_pos.offset
247
+ end
248
+ private :same_position?
249
+
250
+ def hash
251
+ @hash ||= [file, source_pos.offset, issue.issue_code, severity].hash
252
+ end
230
253
  end
231
254
 
232
255
  # Formats a diagnostic for output.
@@ -14,6 +14,8 @@ class Puppet::Pops::Validation::Checker4_0
14
14
  Model = Puppet::Pops::Model
15
15
 
16
16
  attr_reader :acceptor
17
+ attr_reader :migration_checker
18
+
17
19
  # Initializes the validator with a diagnostics producer. This object must respond to
18
20
  # `:will_accept?` and `:accept`.
19
21
  #
@@ -28,6 +30,9 @@ class Puppet::Pops::Validation::Checker4_0
28
30
  @@idem_visitor ||= Puppet::Pops::Visitor.new(self, "idem", 0, 0)
29
31
 
30
32
  @acceptor = diagnostics_producer
33
+
34
+ # Use null migration checker unless given in context
35
+ @migration_checker = (Puppet.lookup(:migration_checker) { Puppet::Pops::Migration::MigrationChecker.new() })
31
36
  end
32
37
 
33
38
  # Validates the entire model by visiting each model element and calling `check`.
@@ -47,8 +52,8 @@ class Puppet::Pops::Validation::Checker4_0
47
52
 
48
53
  # Performs check if this is a vaid hostname expression
49
54
  # @param single_feature_name [String, nil] the name of a single valued hostname feature of the value's container. e.g. 'parent'
50
- def hostname(o, semantic, single_feature_name = nil)
51
- @@hostname_visitor.visit_this_2(self, o, semantic, single_feature_name)
55
+ def hostname(o, semantic)
56
+ @@hostname_visitor.visit_this_1(self, o, semantic)
52
57
  end
53
58
 
54
59
  # Performs check if this is valid as a query
@@ -110,9 +115,9 @@ class Puppet::Pops::Validation::Checker4_0
110
115
  acceptor.accept(Issues::CROSS_SCOPE_ASSIGNMENT, o, :name => varname_string)
111
116
  end
112
117
  end
118
+
113
119
  # TODO: Could scan for reassignment of the same variable if done earlier in the same container
114
120
  # Or if assigning to a parameter (more work).
115
- # TODO: Investigate if there are invalid cases for += assignment
116
121
  end
117
122
 
118
123
  def assign_AccessExpression(o, via_index)
@@ -125,6 +130,10 @@ class Puppet::Pops::Validation::Checker4_0
125
130
  end
126
131
  end
127
132
 
133
+ def assign_LiteralList(o, via_index)
134
+ o.values.each {|x| assign(x) }
135
+ end
136
+
128
137
  def assign_Object(o, via_index)
129
138
  # Can not assign to anything else (differentiate if this is via index or not)
130
139
  # i.e. 10 = 'hello' vs. 10['x'] = 'hello' (the root is reported as being in error in both cases)
@@ -182,12 +191,18 @@ class Puppet::Pops::Validation::Checker4_0
182
191
 
183
192
  def check_AttributesOperation(o)
184
193
  # Append operator use is constrained
185
- parent = o.eContainer
186
- parent = parent.eContainer unless parent.nil?
187
- unless parent.is_a?(Model::ResourceExpression)
188
- acceptor.accept(Issues::UNSUPPORTED_OPERATOR_IN_CONTEXT, o, :operator=>'* =>')
194
+ parent1 = o.eContainer
195
+ case parent1
196
+ when Model::AbstractResource
197
+ when Model::CollectExpression
198
+ else
199
+ # protect against just testing a snippet that has no parent, error message will be a bit strange
200
+ # but it is not for a real program.
201
+ parent2 = parent1.nil? ? o : parent1.eContainer
202
+ unless parent2.is_a?(Model::AbstractResource)
203
+ acceptor.accept(Issues::UNSUPPORTED_OPERATOR_IN_CONTEXT, parent2, :operator=>'* =>')
204
+ end
189
205
  end
190
-
191
206
  rvalue(o.expr)
192
207
  end
193
208
 
@@ -294,22 +309,34 @@ class Puppet::Pops::Validation::Checker4_0
294
309
  if RESERVED_TYPE_NAMES[o.name()]
295
310
  acceptor.accept(Issues::RESERVED_TYPE_NAME, o, {:name => o.name})
296
311
  end
312
+ end
297
313
 
298
- if violator = ends_with_idem(o.body)
299
- acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o})
300
- end
314
+ def check_FunctionDefinition(o)
315
+ # TODO PUP-2080: more strict rule for top - can only be contained in Program (for now)
316
+ # sticking functions in classes would create functions in the class name space
317
+ # but not be special in any other way
318
+ #
319
+ check_NamedDefinition(o)
301
320
  end
302
321
 
303
322
  def check_HostClassDefinition(o)
304
323
  check_NamedDefinition(o)
305
324
  internal_check_no_capture(o)
306
325
  internal_check_reserved_params(o)
326
+ internal_check_no_idem_last(o)
307
327
  end
308
328
 
309
329
  def check_ResourceTypeDefinition(o)
310
330
  check_NamedDefinition(o)
311
331
  internal_check_no_capture(o)
312
332
  internal_check_reserved_params(o)
333
+ internal_check_no_idem_last(o)
334
+ end
335
+
336
+ def internal_check_no_idem_last(o)
337
+ if violator = ends_with_idem(o.body)
338
+ acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o})
339
+ end
313
340
  end
314
341
 
315
342
  def internal_check_capture_last(o)
@@ -364,7 +391,6 @@ class Puppet::Pops::Validation::Checker4_0
364
391
  def check_NodeDefinition(o)
365
392
  # Check that hostnames are valid hostnames (or regular expressions)
366
393
  hostname(o.host_matches, o)
367
- hostname(o.parent, o, 'parent') unless o.parent.nil?
368
394
  top(o.eContainer, o)
369
395
  if violator = ends_with_idem(o.body)
370
396
  acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o})
@@ -407,6 +433,15 @@ class Puppet::Pops::Validation::Checker4_0
407
433
  if o.name =~ /^(?:0x)?[0-9]+$/
408
434
  acceptor.accept(Issues::ILLEGAL_NUMERIC_PARAMETER, o, :name => o.name)
409
435
  end
436
+ return unless o.value
437
+
438
+ if o.value.is_a?(Puppet::Pops::Model::AssignmentExpression)
439
+ [o.value]
440
+ else
441
+ o.value.eAllContents.select {|model| model.is_a? Puppet::Pops::Model::AssignmentExpression }
442
+ end.each do |assignment|
443
+ acceptor.accept(Issues::ILLEGAL_ASSIGNMENT_CONTEXT, assignment)
444
+ end
410
445
  end
411
446
 
412
447
  #relationship_side: resource
@@ -501,14 +536,11 @@ class Puppet::Pops::Validation::Checker4_0
501
536
  #--- HOSTNAME CHECKS
502
537
 
503
538
  # Transforms Array of host matching expressions into a (Ruby) array of AST::HostName
504
- def hostname_Array(o, semantic, single_feature_name)
505
- if single_feature_name
506
- acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature=>single_feature_name, :container=>semantic})
507
- end
508
- o.each {|x| hostname(x, semantic, false) }
539
+ def hostname_Array(o, semantic)
540
+ o.each {|x| hostname(x, semantic) }
509
541
  end
510
542
 
511
- def hostname_String(o, semantic, single_feature_name)
543
+ def hostname_String(o, semantic)
512
544
  # The 3.x checker only checks for illegal characters - if matching /[^-\w.]/ the name is invalid,
513
545
  # but this allows pathological names like "a..b......c", "----"
514
546
  # TODO: Investigate if more illegal hostnames should be flagged.
@@ -518,11 +550,11 @@ class Puppet::Pops::Validation::Checker4_0
518
550
  end
519
551
  end
520
552
 
521
- def hostname_LiteralValue(o, semantic, single_feature_name)
522
- hostname_String(o.value.to_s, o, single_feature_name)
553
+ def hostname_LiteralValue(o, semantic)
554
+ hostname_String(o.value.to_s, o)
523
555
  end
524
556
 
525
- def hostname_ConcatenatedString(o, semantic, single_feature_name)
557
+ def hostname_ConcatenatedString(o, semantic)
526
558
  # Puppet 3.1. only accepts a concatenated string without interpolated expressions
527
559
  if the_expr = o.segments.index {|s| s.is_a?(Model::TextExpression) }
528
560
  acceptor.accept(Issues::ILLEGAL_HOSTNAME_INTERPOLATION, o.segments[the_expr].expr)
@@ -532,32 +564,32 @@ class Puppet::Pops::Validation::Checker4_0
532
564
  else
533
565
  # corner case, may be ok, but lexer may have replaced with plain string, this is
534
566
  # here if it does not
535
- hostname_String(o.segments[0], o.segments[0], false)
567
+ hostname_String(o.segments[0], o.segments[0])
536
568
  end
537
569
  end
538
570
 
539
- def hostname_QualifiedName(o, semantic, single_feature_name)
540
- hostname_String(o.value.to_s, o, single_feature_name)
571
+ def hostname_QualifiedName(o, semantic)
572
+ hostname_String(o.value.to_s, o)
541
573
  end
542
574
 
543
- def hostname_QualifiedReference(o, semantic, single_feature_name)
544
- hostname_String(o.value.to_s, o, single_feature_name)
575
+ def hostname_QualifiedReference(o, semantic)
576
+ hostname_String(o.value.to_s, o)
545
577
  end
546
578
 
547
- def hostname_LiteralNumber(o, semantic, single_feature_name)
579
+ def hostname_LiteralNumber(o, semantic)
548
580
  # always ok
549
581
  end
550
582
 
551
- def hostname_LiteralDefault(o, semantic, single_feature_name)
583
+ def hostname_LiteralDefault(o, semantic)
552
584
  # always ok
553
585
  end
554
586
 
555
- def hostname_LiteralRegularExpression(o, semantic, single_feature_name)
587
+ def hostname_LiteralRegularExpression(o, semantic)
556
588
  # always ok
557
589
  end
558
590
 
559
- def hostname_Object(o, semantic, single_feature_name)
560
- acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature=> single_feature_name || 'hostname', :container=>semantic})
591
+ def hostname_Object(o, semantic)
592
+ acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature => 'hostname', :container => semantic})
561
593
  end
562
594
 
563
595
  #---QUERY CHECKS
@@ -9,6 +9,11 @@ Puppet::Type.type(:group).provide :windows_adsi do
9
9
 
10
10
  has_features :manages_members
11
11
 
12
+ def initialize(value={})
13
+ super(value)
14
+ @deleted = false
15
+ end
16
+
12
17
  def members_insync?(current, should)
13
18
  return false unless current
14
19
 
@@ -17,9 +22,6 @@ Puppet::Type.type(:group).provide :windows_adsi do
17
22
 
18
23
  # Cannot use munge of the group property to canonicalize @should
19
24
  # since the default array_matching comparison is not commutative
20
- should_empty = should.nil? or should.empty?
21
-
22
- return false if current.empty? != should_empty
23
25
 
24
26
  # dupes automatically weeded out when hashes built
25
27
  current_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current)
@@ -72,11 +74,13 @@ Puppet::Type.type(:group).provide :windows_adsi do
72
74
 
73
75
  def delete
74
76
  Puppet::Util::Windows::ADSI::Group.delete(@resource[:name])
77
+
78
+ @deleted = true
75
79
  end
76
80
 
77
81
  # Only flush if we created or modified a group, not deleted
78
82
  def flush
79
- @group.commit if @group
83
+ @group.commit if @group && !@deleted
80
84
  end
81
85
 
82
86
  def gid
@@ -4,6 +4,7 @@ require 'puppet/provider/mount'
4
4
  fstab = nil
5
5
  case Facter.value(:osfamily)
6
6
  when "Solaris"; fstab = "/etc/vfstab"
7
+ when "AIX"; fstab = "/etc/filesystems"
7
8
  else
8
9
  fstab = "/etc/fstab"
9
10
  end
@@ -25,7 +26,12 @@ Puppet::Type.type(:mount).provide(
25
26
  @fields = [:device, :name, :fstype, :options, :dump, :pass]
26
27
  end
27
28
 
28
- text_line :comment, :match => /^\s*#/
29
+ if Facter.value(:osfamily) == "AIX"
30
+ # * is the comment character on AIX /etc/filesystems
31
+ text_line :comment, :match => /^\s*\*/
32
+ else
33
+ text_line :comment, :match => /^\s*#/
34
+ end
29
35
  text_line :blank, :match => /^\s*$/
30
36
 
31
37
  optional_fields = @fields - [:device, :name, :blockdevice]
@@ -36,7 +42,144 @@ Puppet::Type.type(:mount).provide(
36
42
  field_pattern = '(\s*(?>\S+))'
37
43
  text_line :incomplete, :match => /^(?!#{field_pattern}{#{mandatory_fields.length}})/
38
44
 
39
- record_line self.name, :fields => @fields, :separator => /\s+/, :joiner => "\t", :optional => optional_fields
45
+ case Facter.value(:osfamily)
46
+ when "AIX"
47
+ # The only field that is actually ordered is :name. See `man filesystems` on AIX
48
+ @fields = [:name, :account, :boot, :check, :dev, :free, :mount, :nodename,
49
+ :options, :quota, :size, :type, :vfs, :vol, :log]
50
+ self.line_separator = "\n"
51
+ # Override lines and use scan instead of split, because we DON'T want to
52
+ # remove the separators
53
+ def self.lines(text)
54
+ lines = text.split("\n")
55
+ filesystem_stanza = false
56
+ filesystem_index = 0
57
+ ret = Array.new
58
+ lines.each_with_index do |line,i|
59
+ if line.match(%r{^\S+:})
60
+ # Begin new filesystem stanza and save the index
61
+ ret[filesystem_index] = filesystem_stanza.join("\n") if filesystem_stanza
62
+ filesystem_stanza = Array(line)
63
+ filesystem_index = i
64
+ # Eat the preceeding blank line
65
+ ret[i-1] = nil if i > 0 and ret[i-1] and ret[i-1].match(%r{^\s*$})
66
+ nil
67
+ elsif line.match(%r{^(\s*\*.*|\s*)$})
68
+ # Just a comment or blank line; add in place
69
+ ret[i] = line
70
+ else
71
+ # Non-comments or blank lines must be part of a stanza
72
+ filesystem_stanza << line
73
+ end
74
+ end
75
+ # Add the final stanza to the return
76
+ ret[filesystem_index] = filesystem_stanza.join("\n") if filesystem_stanza
77
+ ret = ret.compact.flatten
78
+ ret.reject { |line| line.match(/^\* HEADER/) }
79
+ end
80
+ def self.header
81
+ super.gsub(/^#/,'*')
82
+ end
83
+
84
+ record_line self.name,
85
+ :fields => @fields,
86
+ :separator => /\n/,
87
+ :block_eval => :instance do
88
+
89
+ def post_parse(result)
90
+ property_map = {
91
+ :dev => :device,
92
+ :nodename => :nodename,
93
+ :options => :options,
94
+ :vfs => :fstype,
95
+ }
96
+ # Result is modified in-place instead of being returned; icky!
97
+ memo = result.dup
98
+ result.clear
99
+ # Save the line for later, just in case it is unparsable
100
+ result[:line] = @fields.collect do |field|
101
+ memo[field] if memo[field] != :absent
102
+ end.compact.join("\n")
103
+ result[:record_type] = memo[:record_type]
104
+ special_options = Array.new
105
+ result[:name] = memo[:name].sub(%r{:\s*$},'').strip
106
+ memo.each do |_,k_v|
107
+ if k_v and k_v.is_a?(String) and k_v.match("=")
108
+ attr_name, attr_value = k_v.split("=",2).map(&:strip)
109
+ if attr_map_name = property_map[attr_name.to_sym]
110
+ # These are normal "options" options (see `man filesystems`)
111
+ result[attr_map_name] = attr_value
112
+ else
113
+ # These /etc/filesystem attributes have no mount resource simile,
114
+ # so are added to the "options" property for puppet's sake
115
+ special_options << "#{attr_name}=#{attr_value}"
116
+ end
117
+ if result[:nodename]
118
+ result[:device] = "#{result[:nodename]}:#{result[:device]}"
119
+ result.delete(:nodename)
120
+ end
121
+ end
122
+ end
123
+ result[:options] = [result[:options],special_options.sort].flatten.compact.join(',')
124
+ if ! result[:device]
125
+ result[:device] = :absent
126
+ Puppet.err "Prefetch: Mount[#{result[:name]}]: Field 'device' is missing"
127
+ end
128
+ if ! result[:fstype]
129
+ result[:fstype] = :absent
130
+ Puppet.err "Prefetch: Mount[#{result[:name]}]: Field 'fstype' is missing"
131
+ end
132
+ end
133
+ def to_line(result)
134
+ output = Array.new
135
+ output << "#{result[:name]}:"
136
+ if result[:device] and result[:device].match(%r{^/})
137
+ output << "\tdev\t\t= #{result[:device]}"
138
+ elsif result[:device] and result[:device] != :absent
139
+ if ! result[:device].match(%{^.+:/})
140
+ # Just skip this entry; it was malformed to begin with
141
+ Puppet.err "Mount[#{result[:name]}]: Field 'device' must be in the format of <absolute path> or <host>:<absolute path>"
142
+ return result[:line]
143
+ end
144
+ nodename, path = result[:device].split(":")
145
+ output << "\tdev\t\t= #{path}"
146
+ output << "\tnodename\t= #{nodename}"
147
+ else
148
+ # Just skip this entry; it was malformed to begin with
149
+ Puppet.err "Mount[#{result[:name]}]: Field 'device' is required"
150
+ return result[:line]
151
+ end
152
+ if result[:fstype] and result[:fstype] != :absent
153
+ output << "\tvfs\t\t= #{result[:fstype]}"
154
+ else
155
+ # Just skip this entry; it was malformed to begin with
156
+ Puppet.err "Mount[#{result[:name]}]: Field 'device' is required"
157
+ return result[:line]
158
+ end
159
+ if result[:options]
160
+ options = result[:options].split(',')
161
+ special_options = options.select do |x|
162
+ x.match('=') and
163
+ ["account", "boot", "check", "free", "mount", "size", "type",
164
+ "vol", "log", "quota"].include? x.split('=').first
165
+ end
166
+ options = options - special_options
167
+ special_options.sort.each do |x|
168
+ k, v = x.split("=")
169
+ output << "\t#{k}\t\t= #{v}"
170
+ end
171
+ output << "\toptions\t\t= #{options.join(",")}" unless options.empty?
172
+ end
173
+ if result[:line] and result[:line].split("\n").sort == output.sort
174
+ return "\n#{result[:line]}"
175
+ else
176
+ return "\n#{output.join("\n")}"
177
+ end
178
+ end
179
+ end
180
+ else
181
+ record_line self.name, :fields => @fields, :separator => /\s+/, :joiner => "\t", :optional => optional_fields
182
+ end
40
183
 
41
184
  # Every entry in fstab is :unmounted until we can prove different
42
185
  def self.prefetch_hook(target_records)