puppet 3.7.5 → 3.8.1
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 +5 -5
- data/lib/hiera/puppet_function.rb +15 -4
- data/lib/puppet.rb +5 -2
- data/lib/puppet/application/agent.rb +5 -0
- data/lib/puppet/application/apply.rb +5 -0
- data/lib/puppet/application/device.rb +8 -3
- data/lib/puppet/application/master.rb +5 -0
- data/lib/puppet/defaults.rb +8 -0
- data/lib/puppet/error.rb +27 -1
- data/lib/puppet/file_system.rb +13 -0
- data/lib/puppet/file_system/file19windows.rb +8 -0
- data/lib/puppet/file_system/file_impl.rb +4 -0
- data/lib/puppet/file_system/memory_impl.rb +4 -0
- data/lib/puppet/functions.rb +25 -3
- data/lib/puppet/functions/defined.rb +130 -0
- data/lib/puppet/functions/hiera_include.rb +1 -1
- data/lib/puppet/node/environment.rb +4 -0
- data/lib/puppet/parser/compiler.rb +5 -2
- data/lib/puppet/parser/functions/defined.rb +26 -1
- data/lib/puppet/parser/functions/file.rb +3 -1
- data/lib/puppet/parser/templatewrapper.rb +2 -1
- data/lib/puppet/pops.rb +5 -0
- data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
- data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
- data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +43 -28
- data/lib/puppet/pops/evaluator/runtime3_support.rb +9 -5
- data/lib/puppet/pops/functions/dispatch.rb +6 -1
- data/lib/puppet/pops/issue_reporter.rb +42 -16
- data/lib/puppet/pops/issues.rb +96 -0
- data/lib/puppet/pops/loader/module_loaders.rb +3 -1
- data/lib/puppet/pops/loaders.rb +6 -4
- data/lib/puppet/pops/migration/migration_checker.rb +45 -0
- data/lib/puppet/pops/model/factory.rb +1 -1
- data/lib/puppet/pops/model/model_meta.rb +1 -1
- data/lib/puppet/pops/parser/egrammar.ra +1 -1
- data/lib/puppet/pops/parser/eparser.rb +1 -1
- 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 +8 -8
- data/lib/puppet/pops/parser/lexer_support.rb +46 -20
- 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 +67 -14
- data/lib/puppet/pops/types/type_parser.rb +22 -13
- data/lib/puppet/pops/types/types.rb +21 -3
- 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 +25 -5
- data/lib/puppet/provider/group/windows_adsi.rb +18 -6
- data/lib/puppet/provider/mount/parsed.rb +145 -2
- data/lib/puppet/provider/package/pip.rb +4 -5
- data/lib/puppet/provider/package/zypper.rb +17 -7
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +35 -10
- data/lib/puppet/provider/service/init.rb +7 -0
- data/lib/puppet/provider/user/windows_adsi.rb +8 -1
- data/lib/puppet/provider/zpool/zpool.rb +7 -2
- data/lib/puppet/resource.rb +1 -1
- data/lib/puppet/type/group.rb +1 -1
- data/lib/puppet/type/mount.rb +14 -3
- data/lib/puppet/type/scheduled_task.rb +21 -6
- 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/windows/adsi.rb +36 -11
- data/lib/puppet/version.rb +1 -1
- data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
- data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
- data/spec/integration/parser/collector_spec.rb +7 -0
- data/spec/integration/parser/future_compiler_spec.rb +9 -0
- data/spec/integration/parser/resource_expressions_spec.rb +3 -0
- data/spec/unit/file_system_spec.rb +38 -0
- data/spec/unit/functions/defined_spec.rb +291 -0
- data/spec/unit/functions/hiera_spec.rb +8 -6
- data/spec/unit/functions4_spec.rb +97 -2
- data/spec/unit/parser/functions/file_spec.rb +8 -2
- data/spec/unit/parser/functions/template_spec.rb +1 -1
- 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 +61 -8
- data/spec/unit/pops/issues_spec.rb +16 -16
- data/spec/unit/pops/loaders/module_loaders_spec.rb +5 -0
- data/spec/unit/pops/migration_spec.rb +180 -0
- data/spec/unit/pops/parser/lexer2_spec.rb +152 -1
- data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
- data/spec/unit/pops/transformer/transform_calls_spec.rb +1 -1
- data/spec/unit/pops/types/type_calculator_spec.rb +204 -11
- data/spec/unit/pops/validation_spec.rb +66 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +65 -1
- data/spec/unit/provider/mount/parsed_spec.rb +31 -5
- data/spec/unit/provider/package/pip_spec.rb +19 -7
- data/spec/unit/provider/package/zypper_spec.rb +25 -14
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
- data/spec/unit/provider/service/base_spec.rb +42 -31
- 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 +21 -0
- data/spec/unit/provider/zpool/zpool_spec.rb +47 -10
- data/spec/unit/util/log_spec.rb +113 -0
- data/spec/unit/util/windows/adsi_spec.rb +106 -26
- metadata +10 -2
@@ -2,9 +2,9 @@
|
|
2
2
|
# @api public
|
3
3
|
#
|
4
4
|
module Puppet::Pops::Types::TypeFactory
|
5
|
-
@type_calculator = Puppet::Pops::Types::TypeCalculator.new()
|
6
|
-
|
7
5
|
Types = Puppet::Pops::Types
|
6
|
+
@type_calculator = Types::TypeCalculator.singleton
|
7
|
+
@undef_t = Types::PUndefType.new
|
8
8
|
|
9
9
|
# Produces the Integer type
|
10
10
|
# @api public
|
@@ -66,9 +66,17 @@ module Puppet::Pops::Types::TypeFactory
|
|
66
66
|
end
|
67
67
|
|
68
68
|
# Produces the Optional type, i.e. a short hand for Variant[T, Undef]
|
69
|
+
# If the given 'optional_type' argument is a String, then it will be
|
70
|
+
# converted into a String type that represents that string.
|
71
|
+
#
|
72
|
+
# @param optional_type [String,PAnyType,nil] the optional type
|
73
|
+
# @return [POptionalType] the created type
|
74
|
+
#
|
75
|
+
# @api public
|
76
|
+
#
|
69
77
|
def self.optional(optional_type = nil)
|
70
78
|
t = Types::POptionalType.new
|
71
|
-
t.optional_type = type_of(optional_type)
|
79
|
+
t.optional_type = optional_type.is_a?(String) ? string(optional_type) : type_of(optional_type)
|
72
80
|
t
|
73
81
|
end
|
74
82
|
|
@@ -91,21 +99,50 @@ module Puppet::Pops::Types::TypeFactory
|
|
91
99
|
end
|
92
100
|
|
93
101
|
# Produces the Struct type, either a non parameterized instance representing
|
94
|
-
# all structs (i.e. all hashes) or a hash with
|
95
|
-
#
|
96
|
-
#
|
102
|
+
# all structs (i.e. all hashes) or a hash with entries where the key is
|
103
|
+
# either a literal String, an Enum with one entry, or a String representing exactly one value.
|
104
|
+
# The key type may also be wrapped in a NotUndef or an Optional.
|
97
105
|
#
|
98
|
-
|
106
|
+
# The value can be a ruby class, a String (interpreted as the name of a ruby class) or
|
107
|
+
# a Type.
|
108
|
+
#
|
109
|
+
# @param hash [Hash<Object, Object>] key => value hash
|
110
|
+
# @return [PStructType] the created Struct type
|
111
|
+
#
|
112
|
+
def self.struct(hash = {})
|
113
|
+
tc = @type_calculator
|
99
114
|
t = Types::PStructType.new
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
115
|
+
t.elements = hash.map do |key_type, value_type|
|
116
|
+
value_type = type_of(value_type)
|
117
|
+
raise ArgumentError, 'Struct element value_type must be a Type' unless value_type.is_a?(Types::PAnyType)
|
118
|
+
|
119
|
+
# TODO: Should have stricter name rule
|
120
|
+
if key_type.is_a?(String)
|
121
|
+
raise ArgumentError, 'Struct element key cannot be an empty String' if key_type.empty?
|
122
|
+
key_type = string(key_type)
|
123
|
+
# Must make key optional if the value can be Undef
|
124
|
+
key_type = optional(key_type) if tc.assignable?(value_type, @undef_t)
|
125
|
+
else
|
126
|
+
# assert that the key type is one of String[1], NotUndef[String[1]] and Optional[String[1]]
|
127
|
+
case key_type
|
128
|
+
when Types::PNotUndefType
|
129
|
+
# We can loose the NotUndef wrapper here since String[1] isn't optional anyway
|
130
|
+
key_type = key_type.type
|
131
|
+
s = key_type
|
132
|
+
when Types::POptionalType
|
133
|
+
s = key_type.optional_type
|
134
|
+
else
|
135
|
+
s = key_type
|
136
|
+
end
|
137
|
+
unless (s.is_a?(Puppet::Pops::Types::PStringType) || s.is_a?(Puppet::Pops::Types::PEnumType)) && s.values.size == 1 && !s.values[0].empty?
|
138
|
+
raise ArgumentError, 'Unable to extract a non-empty literal string from Struct member key type' if key_type.empty?
|
139
|
+
end
|
104
140
|
end
|
105
|
-
elem
|
106
|
-
elem.
|
141
|
+
elem = Types::PStructElement.new
|
142
|
+
elem.key_type = key_type
|
143
|
+
elem.value_type = value_type
|
107
144
|
elem
|
108
|
-
end
|
145
|
+
end
|
109
146
|
t
|
110
147
|
end
|
111
148
|
|
@@ -351,6 +388,22 @@ module Puppet::Pops::Types::TypeFactory
|
|
351
388
|
type
|
352
389
|
end
|
353
390
|
|
391
|
+
# Produces a type for NotUndef[T]
|
392
|
+
# The given 'inst_type' can be a string in which case it will be converted into
|
393
|
+
# the type String[inst_type].
|
394
|
+
#
|
395
|
+
# @param inst_type [Type,String] the type to qualify
|
396
|
+
# @return [Puppet::Pops::Types::PNotUndefType] the NotUndef type
|
397
|
+
#
|
398
|
+
# @api public
|
399
|
+
#
|
400
|
+
def self.not_undef(inst_type = nil)
|
401
|
+
type = Types::PNotUndefType.new()
|
402
|
+
inst_type = string(inst_type) if inst_type.is_a?(String)
|
403
|
+
type.type = inst_type
|
404
|
+
type
|
405
|
+
end
|
406
|
+
|
354
407
|
# Produces a type for Type[T]
|
355
408
|
# @api public
|
356
409
|
#
|
@@ -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."
|
@@ -46,6 +46,18 @@ module Puppet::Pops
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
class PNotUndefType < PAnyType
|
50
|
+
module ClassModule
|
51
|
+
def hash
|
52
|
+
[self.class, type].hash
|
53
|
+
end
|
54
|
+
|
55
|
+
def ==(o)
|
56
|
+
self.class == o.class && type == o.type
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
49
61
|
class PType < PAnyType
|
50
62
|
module ClassModule
|
51
63
|
def hash
|
@@ -220,11 +232,17 @@ module Puppet::Pops
|
|
220
232
|
class PStructElement < TypeModelObject
|
221
233
|
module ClassModule
|
222
234
|
def hash
|
223
|
-
[self.class,
|
235
|
+
[self.class, value_type, key_type].hash
|
236
|
+
end
|
237
|
+
|
238
|
+
def name
|
239
|
+
k = key_type
|
240
|
+
k = k.optional_type if k.is_a?(POptionalType)
|
241
|
+
k.values[0]
|
224
242
|
end
|
225
243
|
|
226
244
|
def ==(o)
|
227
|
-
self.class == o.class &&
|
245
|
+
self.class == o.class && value_type == o.value_type && key_type == o.key_type
|
228
246
|
end
|
229
247
|
end
|
230
248
|
end
|
@@ -233,7 +251,7 @@ module Puppet::Pops
|
|
233
251
|
class PStructType < PAnyType
|
234
252
|
module ClassModule
|
235
253
|
def hashed_elements_derived
|
236
|
-
@_hashed ||= elements.reduce({}) {|memo, e| memo[e.name] = e
|
254
|
+
@_hashed ||= elements.reduce({}) {|memo, e| memo[e.name] = e; memo }
|
237
255
|
@_hashed
|
238
256
|
end
|
239
257
|
|
@@ -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`.
|
@@ -182,12 +187,18 @@ class Puppet::Pops::Validation::Checker4_0
|
|
182
187
|
|
183
188
|
def check_AttributesOperation(o)
|
184
189
|
# Append operator use is constrained
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
190
|
+
parent1 = o.eContainer
|
191
|
+
case parent1
|
192
|
+
when Model::AbstractResource
|
193
|
+
when Model::CollectExpression
|
194
|
+
else
|
195
|
+
# protect against just testing a snippet that has no parent, error message will be a bit strange
|
196
|
+
# but it is not for a real program.
|
197
|
+
parent2 = parent1.nil? ? o : parent1.eContainer
|
198
|
+
unless parent2.is_a?(Model::AbstractResource)
|
199
|
+
acceptor.accept(Issues::UNSUPPORTED_OPERATOR_IN_CONTEXT, parent2, :operator=>'* =>')
|
200
|
+
end
|
189
201
|
end
|
190
|
-
|
191
202
|
rvalue(o.expr)
|
192
203
|
end
|
193
204
|
|
@@ -203,6 +214,7 @@ class Puppet::Pops::Validation::Checker4_0
|
|
203
214
|
break # only flag the first
|
204
215
|
end
|
205
216
|
end
|
217
|
+
migration_checker.report_array_last_in_block(o.statements[-1])
|
206
218
|
end
|
207
219
|
|
208
220
|
def check_CallNamedFunctionExpression(o)
|
@@ -361,6 +373,14 @@ class Puppet::Pops::Validation::Checker4_0
|
|
361
373
|
o.values.each {|v| rvalue(v) }
|
362
374
|
end
|
363
375
|
|
376
|
+
def check_LiteralFloat(o)
|
377
|
+
migration_checker.report_ambiguous_float(o)
|
378
|
+
end
|
379
|
+
|
380
|
+
def check_LiteralInteger(o)
|
381
|
+
migration_checker.report_ambiguous_integer(o)
|
382
|
+
end
|
383
|
+
|
364
384
|
def check_NodeDefinition(o)
|
365
385
|
# Check that hostnames are valid hostnames (or regular expressions)
|
366
386
|
hostname(o.host_matches, o)
|
@@ -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,12 +22,17 @@ 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)
|
28
|
+
specified_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
|
29
|
+
|
30
|
+
if @resource[:auth_membership]
|
31
|
+
current_users == specified_users
|
32
|
+
else
|
33
|
+
return true if specified_users.empty?
|
34
|
+
(specified_users.keys.to_a & current_users.keys.to_a) == specified_users.keys.to_a
|
35
|
+
end
|
26
36
|
end
|
27
37
|
|
28
38
|
def members_to_s(users)
|
@@ -49,7 +59,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
49
59
|
end
|
50
60
|
|
51
61
|
def members=(members)
|
52
|
-
group.set_members(members)
|
62
|
+
group.set_members(members, @resource[:auth_membership])
|
53
63
|
end
|
54
64
|
|
55
65
|
def create
|
@@ -65,11 +75,13 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
65
75
|
|
66
76
|
def delete
|
67
77
|
Puppet::Util::Windows::ADSI::Group.delete(@resource[:name])
|
78
|
+
|
79
|
+
@deleted = true
|
68
80
|
end
|
69
81
|
|
70
82
|
# Only flush if we created or modified a group, not deleted
|
71
83
|
def flush
|
72
|
-
@group.commit if @group
|
84
|
+
@group.commit if @group && !@deleted
|
73
85
|
end
|
74
86
|
|
75
87
|
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)
|