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.
- checksums.yaml +4 -4
- data/ext/build_defaults.yaml +8 -35
- data/ext/debian/puppet.default +0 -5
- data/ext/debian/puppet.init +1 -15
- data/lib/hiera/puppet_function.rb +15 -4
- data/lib/puppet/application/agent.rb +5 -0
- data/lib/puppet/application/apply.rb +23 -2
- data/lib/puppet/application/device.rb +8 -3
- data/lib/puppet/application/master.rb +16 -5
- data/lib/puppet/configurer.rb +7 -5
- data/lib/puppet/defaults.rb +18 -0
- data/lib/puppet/environments.rb +1 -1
- data/lib/puppet/error.rb +27 -1
- data/lib/puppet/file_serving/metadata.rb +13 -8
- data/lib/puppet/file_serving/terminus_helper.rb +7 -8
- data/lib/puppet/file_system.rb +13 -0
- data/lib/puppet/file_system/file_impl.rb +4 -0
- data/lib/puppet/file_system/memory_impl.rb +4 -0
- data/lib/puppet/file_system/windows.rb +8 -0
- data/lib/puppet/functions.rb +33 -3
- data/lib/puppet/functions/defined.rb +130 -0
- data/lib/puppet/functions/regsubst.rb +1 -1
- data/lib/puppet/functions/split.rb +1 -1
- data/lib/puppet/indirector/catalog/compiler.rb +1 -1
- data/lib/puppet/indirector/facts/facter.rb +11 -0
- data/lib/puppet/loaders.rb +1 -0
- data/lib/puppet/node.rb +17 -1
- data/lib/puppet/node/environment.rb +4 -0
- data/lib/puppet/parser/ast/pops_bridge.rb +4 -0
- data/lib/puppet/parser/compiler.rb +9 -0
- data/lib/puppet/parser/functions/defined.rb +25 -1
- data/lib/puppet/parser/functions/file.rb +3 -1
- data/lib/puppet/parser/scope.rb +11 -2
- data/lib/puppet/parser/templatewrapper.rb +2 -1
- data/lib/puppet/pops.rb +4 -0
- data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
- data/lib/puppet/pops/evaluator/closure.rb +28 -2
- data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
- data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +4 -0
- data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +4 -0
- data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
- data/lib/puppet/pops/evaluator/epp_evaluator.rb +7 -2
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +48 -14
- data/lib/puppet/pops/evaluator/runtime3_support.rb +10 -5
- data/lib/puppet/pops/functions/dispatch.rb +6 -1
- data/lib/puppet/pops/functions/dispatcher.rb +7 -1
- data/lib/puppet/pops/issue_reporter.rb +42 -16
- data/lib/puppet/pops/issues.rb +116 -2
- data/lib/puppet/pops/loader/loader.rb +11 -0
- data/lib/puppet/pops/loader/loader_paths.rb +67 -6
- data/lib/puppet/pops/loader/module_loaders.rb +19 -8
- data/lib/puppet/pops/loader/puppet_function_instantiator.rb +78 -0
- data/lib/puppet/pops/loaders.rb +6 -4
- data/lib/puppet/pops/migration/migration_checker.rb +54 -0
- data/lib/puppet/pops/model/factory.rb +5 -1
- data/lib/puppet/pops/model/model_label_provider.rb +2 -0
- data/lib/puppet/pops/model/model_meta.rb +5 -1
- data/lib/puppet/pops/parser/egrammar.ra +9 -10
- data/lib/puppet/pops/parser/eparser.rb +1061 -1047
- data/lib/puppet/pops/parser/epp_support.rb +18 -9
- data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
- data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
- data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
- data/lib/puppet/pops/parser/lexer2.rb +29 -12
- data/lib/puppet/pops/parser/lexer_support.rb +52 -23
- data/lib/puppet/pops/parser/parser_support.rb +11 -14
- data/lib/puppet/pops/parser/slurp_support.rb +22 -6
- data/lib/puppet/pops/types/type_calculator.rb +156 -55
- data/lib/puppet/pops/types/type_factory.rb +66 -13
- data/lib/puppet/pops/types/type_parser.rb +22 -13
- data/lib/puppet/pops/types/types.rb +23 -4
- data/lib/puppet/pops/types/types_meta.rb +13 -2
- data/lib/puppet/pops/validation.rb +25 -2
- data/lib/puppet/pops/validation/checker4_0.rb +63 -31
- data/lib/puppet/provider/group/windows_adsi.rb +8 -4
- data/lib/puppet/provider/mount/parsed.rb +145 -2
- data/lib/puppet/provider/package/apt.rb +1 -1
- data/lib/puppet/provider/package/pip.rb +11 -2
- data/lib/puppet/provider/package/pkgng.rb +134 -0
- data/lib/puppet/provider/package/portage.rb +1 -1
- data/lib/puppet/provider/package/ports.rb +0 -3
- data/lib/puppet/provider/package/windows/exe_package.rb +0 -1
- data/lib/puppet/provider/package/windows/msi_package.rb +0 -1
- data/lib/puppet/provider/package/zypper.rb +50 -15
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +32 -7
- data/lib/puppet/provider/service/debian.rb +1 -1
- data/lib/puppet/provider/service/init.rb +7 -0
- data/lib/puppet/provider/user/openbsd.rb +1 -0
- data/lib/puppet/provider/user/windows_adsi.rb +45 -2
- data/lib/puppet/reference/indirection.rb +1 -1
- data/lib/puppet/resource.rb +1 -1
- data/lib/puppet/resource/catalog.rb +0 -4
- data/lib/puppet/settings.rb +19 -0
- data/lib/puppet/type/file.rb +1 -0
- data/lib/puppet/type/file/ensure.rb +1 -1
- data/lib/puppet/type/mount.rb +9 -1
- data/lib/puppet/type/scheduled_task.rb +13 -0
- data/lib/puppet/type/tidy.rb +3 -1
- data/lib/puppet/type/user.rb +32 -0
- data/lib/puppet/type/yumrepo.rb +5 -5
- data/lib/puppet/util/log.rb +50 -8
- data/lib/puppet/util/log/destinations.rb +23 -2
- data/lib/puppet/util/logging.rb +37 -1
- data/lib/puppet/util/run_mode.rb +1 -14
- data/lib/puppet/util/windows/adsi.rb +130 -58
- data/lib/puppet/version.rb +1 -1
- data/man/man5/puppet.conf.5 +48 -6
- data/man/man8/extlookup2hiera.8 +1 -1
- data/man/man8/puppet-agent.8 +4 -1
- data/man/man8/puppet-apply.8 +4 -1
- data/man/man8/puppet-ca.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-cert.8 +1 -1
- data/man/man8/puppet-certificate.8 +1 -1
- data/man/man8/puppet-certificate_request.8 +1 -1
- data/man/man8/puppet-certificate_revocation_list.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +6 -3
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-file.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-inspect.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-master.8 +4 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-resource_type.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +1 -1
- data/spec/fixtures/unit/data_providers/environments/production/lib/puppet/functions/environment/data.rb +3 -1
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/functions/data.pp +6 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/lib/puppet/bindings/xyz/default.rb +9 -0
- data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/manifests/init.pp +9 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcalled.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller4.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/callingpuppet.rb +5 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/functions/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/manifests/init.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/metadata.json +10 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/subspace/hello.pp +3 -0
- data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +1 -10
- data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
- data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
- data/spec/fixtures/unit/provider/package/pkgng/pkg.info +8 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query +1 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +1 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.version +3 -0
- data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-empty.out +3 -0
- data/spec/integration/application/apply_spec.rb +49 -0
- data/spec/integration/faces/plugin_spec.rb +0 -4
- data/spec/integration/indirector/facts/facter_spec.rb +59 -0
- data/spec/integration/parser/compiler_spec.rb +850 -0
- data/spec/integration/parser/resource_expressions_spec.rb +3 -0
- data/spec/integration/parser/scope_spec.rb +26 -5
- data/spec/integration/transaction_spec.rb +1 -1
- data/spec/integration/type/file_spec.rb +318 -41
- data/spec/integration/util/windows/security_spec.rb +14 -5
- data/spec/lib/matchers/resource.rb +22 -1
- data/spec/lib/puppet_spec/matchers.rb +6 -4
- data/spec/unit/application/master_spec.rb +33 -7
- data/spec/unit/data_providers/function_data_provider_spec.rb +10 -1
- data/spec/unit/file_serving/metadata_spec.rb +1 -1
- data/spec/unit/file_serving/terminus_helper_spec.rb +2 -3
- data/spec/unit/file_system_spec.rb +38 -0
- data/spec/unit/functions/defined_spec.rb +289 -0
- data/spec/unit/functions/hiera_spec.rb +8 -6
- data/spec/unit/functions/regsubst_spec.rb +4 -0
- data/spec/unit/functions/split_spec.rb +8 -0
- data/spec/unit/functions4_spec.rb +97 -2
- data/spec/unit/indirector/facts/facter_spec.rb +7 -0
- data/spec/unit/node_spec.rb +6 -0
- data/spec/unit/parser/functions/file_spec.rb +7 -1
- data/spec/unit/parser/functions/template_spec.rb +1 -1
- data/spec/unit/parser/scope_spec.rb +2 -2
- data/spec/unit/parser/templatewrapper_spec.rb +1 -1
- data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +84 -18
- data/spec/unit/pops/evaluator/variables_spec.rb +1 -1
- data/spec/unit/pops/issues_spec.rb +16 -16
- data/spec/unit/pops/loaders/loaders_spec.rb +106 -48
- data/spec/unit/pops/migration_spec.rb +53 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +142 -1
- data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
- data/spec/unit/pops/types/type_calculator_spec.rb +205 -12
- data/spec/unit/pops/validation_spec.rb +66 -0
- data/spec/unit/pops/validator/validator_spec.rb +1 -1
- data/spec/unit/provider/group/windows_adsi_spec.rb +57 -9
- data/spec/unit/provider/mount/parsed_spec.rb +31 -5
- data/spec/unit/provider/package/apt_spec.rb +5 -0
- data/spec/unit/provider/package/pip_spec.rb +9 -0
- data/spec/unit/provider/package/pkgng_spec.rb +172 -0
- data/spec/unit/provider/package/windows/exe_package_spec.rb +0 -1
- data/spec/unit/provider/package/windows/msi_package_spec.rb +0 -1
- data/spec/unit/provider/package/zypper_spec.rb +50 -19
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
- data/spec/unit/provider/service/base_spec.rb +38 -27
- data/spec/unit/provider/service/debian_spec.rb +8 -0
- data/spec/unit/provider/service/freebsd_spec.rb +1 -0
- data/spec/unit/provider/service/gentoo_spec.rb +1 -0
- data/spec/unit/provider/service/init_spec.rb +18 -0
- data/spec/unit/provider/service/openbsd_spec.rb +1 -0
- data/spec/unit/provider/service/redhat_spec.rb +1 -0
- data/spec/unit/provider/user/windows_adsi_spec.rb +134 -5
- data/spec/unit/settings_spec.rb +11 -0
- data/spec/unit/util/log_spec.rb +113 -0
- data/spec/unit/util/windows/adsi_spec.rb +135 -41
- data/spec/unit/util/windows/sid_spec.rb +0 -10
- 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
|
-
|
348
|
-
|
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
|
-
|
404
|
-
|
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
|
-
|
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,
|
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 &&
|
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
|
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
|
-
|
139
|
-
|
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
|
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
|
51
|
-
@@hostname_visitor.
|
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
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
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
|
-
|
299
|
-
|
300
|
-
|
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
|
505
|
-
|
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
|
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
|
522
|
-
hostname_String(o.value.to_s, o
|
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
|
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]
|
567
|
+
hostname_String(o.segments[0], o.segments[0])
|
536
568
|
end
|
537
569
|
end
|
538
570
|
|
539
|
-
def hostname_QualifiedName(o, semantic
|
540
|
-
hostname_String(o.value.to_s, o
|
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
|
544
|
-
hostname_String(o.value.to_s, o
|
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
|
579
|
+
def hostname_LiteralNumber(o, semantic)
|
548
580
|
# always ok
|
549
581
|
end
|
550
582
|
|
551
|
-
def hostname_LiteralDefault(o, semantic
|
583
|
+
def hostname_LiteralDefault(o, semantic)
|
552
584
|
# always ok
|
553
585
|
end
|
554
586
|
|
555
|
-
def hostname_LiteralRegularExpression(o, semantic
|
587
|
+
def hostname_LiteralRegularExpression(o, semantic)
|
556
588
|
# always ok
|
557
589
|
end
|
558
590
|
|
559
|
-
def hostname_Object(o, semantic
|
560
|
-
acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature=>
|
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
|
-
|
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
|
-
|
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)
|