diff options
-rw-r--r-- | lib/chef/property.rb | 53 | ||||
-rw-r--r-- | lib/chef/resource.rb | 53 | ||||
-rw-r--r-- | spec/unit/property/validation_spec.rb | 5 |
3 files changed, 42 insertions, 69 deletions
diff --git a/lib/chef/property.rb b/lib/chef/property.rb index d832a36f85..408090d37b 100644 --- a/lib/chef/property.rb +++ b/lib/chef/property.rb @@ -39,41 +39,14 @@ class Chef # Create a reusable property type that can be used in multiple properties # in different resources. # - # @param type [Object,Array<Object>] The type(s) of this property. - # If present, this is prepended to the `is` validation option. - # If this is a Chef::Property, `specialize` is called on it to create the - # new property instead of prepending to `is`. - # @param options [Hash<Symbol,Object>] Validation options. see #property for + # @param options [Hash<Symbol,Object>] Validation options. See Chef::Resource.property for # the list of options. # - # @example Bare property_type - # property_type() + # @example + # Property.derive(default: 'hi') # - # @example With just a type - # property_type(String) - # - # @example With just options - # property_type(default: 'hi') - # - # @example With type and options - # property_type(String, default: 'hi') - # - def self.create(type=NOT_PASSED, **options) - # Inherit from the property type, if one is passed - if type.is_a?(self) - type.specialize(**options) - - else - if type != NOT_PASSED - # If a type was passed, combine it with "is" (if a type was passed) - if options[:is] - options[:is] = ([ type ] + [ options[:is] ]).flatten(1) - else - options[:is] = type - end - end - new(**options) - end + def self.derive(**options) + new(**options) end # @@ -102,9 +75,6 @@ class Chef # be run in the context of the instance (and able to access other # properties) and cached. If not, the value will be frozen with Object#freeze # to prevent users from modifying it in an instance. - # @option options [Proc] :computed The value this property will return if - # the user does not set one. If this is `lazy`, it will be run in the - # context of the instance (and able to access other properties). # @option options [Proc] :coerce A proc which will be called to # transform the user input to canonical form. The value is passed in, # and the transformed value returned as output. Lazy values will *not* @@ -213,15 +183,6 @@ class Chef end # - # Whether this property has a computed default value. - # - # @return [Boolean] - # - def has_computed? - options.has_key?(:computed) - end - - # # Whether this property is required or not. # # @return [Boolean] @@ -432,7 +393,7 @@ class Chef end # - # Specialize this Property by making a duplicate with some added or + # Derive a new Property that is just like this one, except with some added or # changed options. # # @param options [Hash<Symbol,Object>] List of options that would be passed @@ -440,7 +401,7 @@ class Chef # # @return [Property] The new property type. # - def specialize(**modified_options) + def derive(**modified_options) Property.new(**options.merge(**modified_options)) end diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index dcbca806fe..5e9ba42703 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -779,37 +779,49 @@ class Chef def self.property(name, type=NOT_PASSED, **options) name = name.to_sym + options.merge!(name: name, declared_in: self) + + if type == NOT_PASSED + # If a type is not passed, the property derives from the + # superclass property (if any) + if properties.has_key?(name) + property = properties[name].derive(**options) + else + property = property_type(**options) + end + + # If a Property is specified, derive a new one from that. + elsif type.is_a?(Property) || (type.is_a?(Class) && type <= Property) + property = type.derive(**options) + + # If a primitive type was passed, combine it with "is" + else + if options[:is] + options[:is] = ([ type ] + [ options[:is] ]).flatten(1) + else + options[:is] = type + end + property = property_type(**options) + end + local_properties = properties(false) - type = properties[name] if type == NOT_PASSED && properties[name] - local_properties[name] = property_type(type, name: name, declared_in: self, **options) - local_properties[name].emit_dsl + local_properties[name] = property + + property.emit_dsl end # # Create a reusable property type that can be used in multiple properties # in different resources. # - # @param type [Object,Array<Object>] The type(s) of this property. - # If present, this is prepended to the `is` validation option. - # If this is a Chef::Property, `specialize` is called on it to create the - # new property instead of prepending to `is`. # @param options [Hash<Symbol,Object>] Validation options. see #property for # the list of options. # - # @example Bare property_type - # property_type() - # - # @example With just a type - # property_type(String) - # - # @example With just options + # @example # property_type(default: 'hi') # - # @example With type and options - # property_type(String, default: 'hi') - # - def self.property_type(type=NOT_PASSED, **options) - Property.create(type, **options) + def self.property_type(**options) + Property.derive(**options) end # @@ -1405,9 +1417,6 @@ class Chef define_method(:load_current_resource) {} end end - def self.default_action=(action_name) - default_action(action_name) - end # # Internal Resource Interface (for Chef) diff --git a/spec/unit/property/validation_spec.rb b/spec/unit/property/validation_spec.rb index 259501d4d8..a3649d228c 100644 --- a/spec/unit/property/validation_spec.rb +++ b/spec/unit/property/validation_spec.rb @@ -581,8 +581,11 @@ describe "Chef::Resource.property validation" do expect(resource.x).to eq 1 end it "value nil is invalid" do + expect { resource.x nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError Chef::Config[:treat_deprecation_warnings_as_errors] = false - expect { resource.x nil }.to raise_error Chef::Exceptions::ValidationFailed + resource.x 1 + expect(resource.x nil).to eq 1 + expect(resource.x).to eq 1 end end end |