1
1
require 'pathname'
2
2
require 'puppet/resource_api/data_type_handling'
3
3
require 'puppet/resource_api/glue'
4
+ require 'puppet/resource_api/parameter'
5
+ require 'puppet/resource_api/property'
4
6
require 'puppet/resource_api/puppet_context' unless RUBY_PLATFORM == 'java'
7
+ require 'puppet/resource_api/read_only_parameter'
5
8
require 'puppet/resource_api/type_definition'
9
+ require 'puppet/resource_api/value_creator'
6
10
require 'puppet/resource_api/version'
7
11
require 'puppet/type'
8
12
require 'puppet/util/network_device'
@@ -174,13 +178,23 @@ def to_resource
174
178
# TODO: using newparam everywhere would suppress change reporting
175
179
# that would allow more fine-grained reporting through context,
176
180
# but require more invest in hooking up the infrastructure to emulate existing data
177
- param_or_property = if [ :read_only , :parameter , :namevar ] . include? options [ :behaviour ]
178
- :newparam
179
- else
180
- :newproperty
181
- end
181
+ if [ :parameter , :namevar ] . include? options [ :behaviour ]
182
+ param_or_property = :newparam
183
+ parent = Puppet ::ResourceApi ::Parameter
184
+ elsif options [ :behaviour ] == :read_only
185
+ param_or_property = :newparam
186
+ parent = Puppet ::ResourceApi ::ReadOnlyParameter
187
+ else
188
+ param_or_property = :newproperty
189
+ parent = Puppet ::ResourceApi ::Property
190
+ end
182
191
183
- send ( param_or_property , name . to_sym ) do
192
+ # This call creates a new parameter or property with all work-arounds or
193
+ # customizations required by the Resource API applied. Under the hood,
194
+ # this maps to the relevant DSL methods in Puppet::Type. See
195
+ # https://puppet.com/docs/puppet/6.0/custom_types.html#reference-5883
196
+ # for details.
197
+ send ( param_or_property , name . to_sym , parent : parent ) do
184
198
unless options [ :type ]
185
199
raise Puppet ::DevError , "#{ definition [ :name ] } .#{ name } has no type"
186
200
end
@@ -191,144 +205,32 @@ def to_resource
191
205
warn ( "#{ definition [ :name ] } .#{ name } has no docs" )
192
206
end
193
207
194
- if options [ :behaviour ] == :namevar
195
- isnamevar
196
- end
197
-
198
- # read-only values do not need type checking, but can have default values
199
- if options [ :behaviour ] != :read_only && options . key? ( :default )
200
- if options . key? :default
201
- if options [ :default ] == false
202
- # work around https://tickets.puppetlabs.com/browse/PUP-2368
203
- defaultto :false # rubocop:disable Lint/BooleanSymbol
204
- elsif options [ :default ] == true
205
- # work around https://tickets.puppetlabs.com/browse/PUP-2368
206
- defaultto :true # rubocop:disable Lint/BooleanSymbol
207
- else
208
- # marshal the default option to decouple that from the actual value.
209
- # we cache the dumped value in `marshalled`, but use a block to unmarshal
210
- # everytime the value is requested. Objects that can't be marshalled
211
- # See https://stackoverflow.com/a/8206537/4918
212
- marshalled = Marshal . dump ( options [ :default ] )
213
- defaultto { Marshal . load ( marshalled ) } # rubocop:disable Security/MarshalLoad
214
- end
215
- end
208
+ # The initialize method is called when puppet core starts building up
209
+ # type objects. The core passes in a hash of shape { resource:
210
+ # #<Puppet::Type::TypeName> }. We use this to pass through the
211
+ # required configuration data to the parent (see
212
+ # Puppet::ResourceApi::Property, Puppet::ResourceApi::Parameter and
213
+ # Puppet::ResourceApi::ReadOnlyParameter).
214
+ define_method ( :initialize ) do |resource_hash |
215
+ super ( definition [ :name ] , self . class . data_type , name , resource_hash )
216
216
end
217
217
218
- if name == :ensure
219
- def insync? ( is )
220
- rs_value . to_s == is . to_s
221
- end
218
+ # get pops data type object for this parameter or property
219
+ define_singleton_method ( :data_type ) do
220
+ @rsapi_data_type ||= Puppet ::ResourceApi ::DataTypeHandling . parse_puppet_type (
221
+ name ,
222
+ options [ :type ] ,
223
+ )
222
224
end
223
225
224
- type = Puppet ::ResourceApi ::DataTypeHandling . parse_puppet_type (
225
- name ,
226
- options [ :type ] ,
226
+ # from ValueCreator call create_values which makes alias values and
227
+ # default values for properties and params
228
+ Puppet ::ResourceApi ::ValueCreator . create_values (
229
+ self ,
230
+ data_type ,
231
+ param_or_property ,
232
+ options ,
227
233
)
228
-
229
- if param_or_property == :newproperty
230
- define_method ( :should ) do
231
- if name == :ensure && rs_value . is_a? ( String )
232
- rs_value . to_sym
233
- elsif rs_value == false
234
- # work around https://tickets.puppetlabs.com/browse/PUP-2368
235
- :false # rubocop:disable Lint/BooleanSymbol
236
- elsif rs_value == true
237
- # work around https://tickets.puppetlabs.com/browse/PUP-2368
238
- :true # rubocop:disable Lint/BooleanSymbol
239
- else
240
- rs_value
241
- end
242
- end
243
-
244
- define_method ( :should= ) do |value |
245
- @shouldorig = value
246
-
247
- if name == :ensure
248
- value = value . to_s
249
- end
250
-
251
- # Puppet requires the @should value to always be stored as an array. We do not use this
252
- # for anything else
253
- # @see Puppet::Property.should=(value)
254
- @should = [
255
- Puppet ::ResourceApi ::DataTypeHandling . mungify (
256
- type ,
257
- value ,
258
- "#{ definition [ :name ] } .#{ name } " ,
259
- Puppet ::ResourceApi . caller_is_resource_app? ,
260
- ) ,
261
- ]
262
- end
263
-
264
- # used internally
265
- # @returns the final mungified value of this property
266
- define_method ( :rs_value ) do
267
- @should ? @should . first : @should
268
- end
269
- else
270
- define_method ( :value ) do
271
- @value
272
- end
273
-
274
- define_method ( :value= ) do |value |
275
- if options [ :behaviour ] == :read_only
276
- raise Puppet ::ResourceError , "Attempting to set `#{ name } ` read_only attribute value to `#{ value } `"
277
- end
278
-
279
- @value = Puppet ::ResourceApi ::DataTypeHandling . mungify (
280
- type ,
281
- value ,
282
- "#{ definition [ :name ] } .#{ name } " ,
283
- Puppet ::ResourceApi . caller_is_resource_app? ,
284
- )
285
- end
286
-
287
- # used internally
288
- # @returns the final mungified value of this parameter
289
- define_method ( :rs_value ) do
290
- @value
291
- end
292
- end
293
-
294
- # puppet symbolizes some values through puppet/parameter/value.rb (see .convert()), but (especially) Enums
295
- # are strings. specifying a munge block here skips the value_collection fallback in puppet/parameter.rb's
296
- # default .unsafe_munge() implementation.
297
- munge { |v | v }
298
-
299
- # provide hints to `puppet type generate` for better parsing
300
- if type . instance_of? Puppet ::Pops ::Types ::POptionalType
301
- type = type . type
302
- end
303
-
304
- case type
305
- when Puppet ::Pops ::Types ::PStringType
306
- # require any string value
307
- Puppet ::ResourceApi . def_newvalues ( self , param_or_property , %r{} )
308
- when Puppet ::Pops ::Types ::PBooleanType
309
- Puppet ::ResourceApi . def_newvalues ( self , param_or_property , 'true' , 'false' )
310
- aliasvalue true , 'true'
311
- aliasvalue false , 'false'
312
- aliasvalue :true , 'true' # rubocop:disable Lint/BooleanSymbol
313
- aliasvalue :false , 'false' # rubocop:disable Lint/BooleanSymbol
314
-
315
- when Puppet ::Pops ::Types ::PIntegerType
316
- Puppet ::ResourceApi . def_newvalues ( self , param_or_property , %r{^-?\d +$} )
317
- when Puppet ::Pops ::Types ::PFloatType , Puppet ::Pops ::Types ::PNumericType
318
- Puppet ::ResourceApi . def_newvalues ( self , param_or_property , Puppet ::Pops ::Patterns ::NUMERIC )
319
- end
320
-
321
- if param_or_property == :newproperty
322
- # stop puppet from trying to call into the provider when
323
- # no pre-defined values have been specified
324
- # "This is not the provider you are looking for." -- Obi-Wan Kaniesobi.
325
- def call_provider ( value ) ; end
326
- end
327
-
328
- case options [ :type ]
329
- when 'Enum[present, absent]'
330
- Puppet ::ResourceApi . def_newvalues ( self , param_or_property , 'absent' , 'present' )
331
- end
332
234
end
333
235
end
334
236
@@ -582,17 +484,6 @@ def self.class_name_from_type_name(type_name)
582
484
type_name . to_s . split ( '_' ) . map ( &:capitalize ) . join
583
485
end
584
486
585
- # Add the value to `this` property or param, depending on whether param_or_property is `:newparam`, or `:newproperty`
586
- def self . def_newvalues ( this , param_or_property , *values )
587
- if param_or_property == :newparam
588
- this . newvalues ( *values )
589
- else
590
- values . each do |v |
591
- this . newvalue ( v ) { }
592
- end
593
- end
594
- end
595
-
596
487
def self . caller_is_resource_app?
597
488
caller . any? { |c | c . match ( %r{application/resource.rb:} ) }
598
489
end
0 commit comments