summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-06-23 16:28:39 -0700
committerJohn Keiser <john@johnkeiser.com>2015-06-23 16:28:39 -0700
commitab34e3cd83d545b5da19113d723eeebcab1e77e2 (patch)
treea55e57a7bfd1f7391e801b7f821f597b5ad6d284 /lib
parent2d4e68e84540c536508c9f33fc1e47c3d8ff60f6 (diff)
parent4f55ea5d8e4b1a684163028b0df80b8d86851adf (diff)
downloadchef-ab34e3cd83d545b5da19113d723eeebcab1e77e2.tar.gz
Merge branch 'jk/property-base'
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/mixin/params_validate.rb479
-rw-r--r--lib/chef/resource.rb114
-rw-r--r--lib/chef/resource/lwrp_base.rb8
3 files changed, 470 insertions, 131 deletions
diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb
index 78d72dc801..f7d52a19cf 100644
--- a/lib/chef/mixin/params_validate.rb
+++ b/lib/chef/mixin/params_validate.rb
@@ -16,6 +16,8 @@
# limitations under the License.
class Chef
+ NOT_PASSED = Object.new
+
class DelayedEvaluator < Proc
end
module Mixin
@@ -65,7 +67,7 @@ class Chef
true
when Hash
validation.each do |check, carg|
- check_method = "_pv_#{check.to_s}"
+ check_method = "_pv_#{check}"
if self.respond_to?(check_method, true)
self.send(check_method, opts, key, carg)
else
@@ -81,162 +83,407 @@ class Chef
DelayedEvaluator.new(&block)
end
- def set_or_return(symbol, arg, validation)
- iv_symbol = "@#{symbol.to_s}".to_sym
- if arg == nil && self.instance_variable_defined?(iv_symbol) == true
- ivar = self.instance_variable_get(iv_symbol)
- if(ivar.is_a?(DelayedEvaluator))
- validate({ symbol => ivar.call }, { symbol => validation })[symbol]
- else
- ivar
- end
+ def set_or_return(symbol, value, validation)
+ symbol = symbol.to_sym
+ iv_symbol = :"@#{symbol}"
+
+ # Steal default, coerce, name_property and required from validation
+ # so that we can handle the order in which they are applied
+ validation = validation.dup
+ if validation.has_key?(:default)
+ default = validation.delete(:default)
+ elsif validation.has_key?('default')
+ default = validation.delete('default')
else
- if(arg.is_a?(DelayedEvaluator))
- val = arg
+ default = NOT_PASSED
+ end
+ coerce = validation.delete(:coerce)
+ coerce ||= validation.delete('coerce')
+ name_property = validation.delete(:name_property)
+ name_property ||= validation.delete('name_property')
+ name_property ||= validation.delete(:name_attribute)
+ name_property ||= validation.delete('name_attribute')
+ required = validation.delete(:required)
+ required ||= validation.delete('required')
+
+ opts = {}
+ # If the user passed NOT_PASSED, or passed nil, then this is a get.
+ if value == NOT_PASSED || (value.nil? && !explicitly_allows_nil?(symbol, validation))
+
+ # Get the value if there is one
+ if self.instance_variable_defined?(iv_symbol)
+ opts[symbol] = self.instance_variable_get(iv_symbol)
+
+ # Handle lazy values
+ if opts[symbol].is_a?(DelayedEvaluator)
+ if opts[symbol].arity >= 1
+ opts[symbol] = opts[symbol].call(self)
+ else
+ opts[symbol] = opts[symbol].call
+ end
+
+ # Coerce and validate the default value
+ _pv_required(opts, symbol, required, explicitly_allows_nil?(symbol, validation)) if required
+ _pv_coerce(opts, symbol, coerce) if coerce
+ validate(opts, { symbol => validation })
+ end
+
+ # Get the default value
else
- val = validate({ symbol => arg }, { symbol => validation })[symbol]
+ _pv_required(opts, symbol, required, explicitly_allows_nil?(symbol, validation)) if required
+ _pv_default(opts, symbol, default) unless default == NOT_PASSED
+ _pv_name_property(opts, symbol, name_property)
+
+ if opts.has_key?(symbol)
+ # Handle lazy defaults.
+ if opts[symbol].is_a?(DelayedEvaluator)
+ if opts[symbol].arity >= 1
+ opts[symbol] = opts[symbol].call(self)
+ else
+ opts[symbol] = instance_eval(&opts[symbol])
+ end
+ end
- # Handle the case where the "default" was a DelayedEvaluator. In
- # this case, the block yields an optional parameter of +self+,
- # which is the equivalent of "new_resource"
- if val.is_a?(DelayedEvaluator)
- val = val.call(self)
+ # Coerce and validate the default value
+ _pv_required(opts, symbol, required, explicitly_allows_nil?(symbol, validation)) if required
+ _pv_coerce(opts, symbol, coerce) if coerce
+ # We presently do not validate defaults, for backwards compatibility.
+# validate(opts, { symbol => validation })
+
+ # Defaults are presently "stickily" set on the instance
+ self.instance_variable_set(iv_symbol, opts[symbol])
end
end
- self.instance_variable_set(iv_symbol, val)
+
+ # Set the value
+ else
+ opts[symbol] = value
+ unless opts[symbol].is_a?(DelayedEvaluator)
+ # Coerce and validate the value
+ _pv_required(opts, symbol, required, explicitly_allows_nil?(symbol, validation)) if required
+ _pv_coerce(opts, symbol, coerce) if coerce
+ validate(opts, { symbol => validation })
+ end
+
+ self.instance_variable_set(iv_symbol, opts[symbol])
end
+
+ opts[symbol]
end
private
- # Return the value of a parameter, or nil if it doesn't exist.
- def _pv_opts_lookup(opts, key)
- if opts.has_key?(key.to_s)
- opts[key.to_s]
- elsif opts.has_key?(key.to_sym)
- opts[key.to_sym]
- else
- nil
- end
+ def explicitly_allows_nil?(key, validation)
+ validation.has_key?(:is) && _pv_is({ key => nil }, key, validation[:is], raise_error: false)
+ end
+
+ # Return the value of a parameter, or nil if it doesn't exist.
+ def _pv_opts_lookup(opts, key)
+ if opts.has_key?(key.to_s)
+ opts[key.to_s]
+ elsif opts.has_key?(key.to_sym)
+ opts[key.to_sym]
+ else
+ nil
+ end
+ end
+
+ # Raise an exception if the parameter is not found.
+ def _pv_required(opts, key, is_required=true, explicitly_allows_nil=false)
+ if is_required
+ return true if opts.has_key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?)
+ return true if opts.has_key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?)
+ raise Exceptions::ValidationFailed, "Required argument #{key} is missing!"
end
+ end
- # Raise an exception if the parameter is not found.
- def _pv_required(opts, key, is_required=true)
- if is_required
- if (opts.has_key?(key.to_s) && !opts[key.to_s].nil?) ||
- (opts.has_key?(key.to_sym) && !opts[key.to_sym].nil?)
- true
- else
- raise Exceptions::ValidationFailed, "Required argument #{key} is missing!"
- end
+ #
+ # List of things values must be equal to.
+ #
+ # Uses Ruby's `==` to evaluate (equal_to == value). At least one must
+ # match for the value to be valid.
+ #
+ # `nil` passes this validation automatically.
+ #
+ # @return [Array,nil] List of things values must be equal to, or nil if
+ # equal_to is unspecified.
+ #
+ def _pv_equal_to(opts, key, to_be)
+ value = _pv_opts_lookup(opts, key)
+ unless value.nil?
+ to_be = Array(to_be)
+ to_be.each do |tb|
+ return true if value == tb
end
+ raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}."
end
+ end
- def _pv_equal_to(opts, key, to_be)
- value = _pv_opts_lookup(opts, key)
- unless value.nil?
- passes = false
- Array(to_be).each do |tb|
- passes = true if value == tb
- end
- unless passes
- raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}."
- end
+ #
+ # List of things values must be instances of.
+ #
+ # Uses value.kind_of?(kind_of) to evaluate. At least one must match for
+ # the value to be valid.
+ #
+ # `nil` automatically passes this validation.
+ #
+ def _pv_kind_of(opts, key, to_be)
+ value = _pv_opts_lookup(opts, key)
+ unless value.nil?
+ to_be = Array(to_be)
+ to_be.each do |tb|
+ return true if value.kind_of?(tb)
end
+ raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}."
end
+ end
- # Raise an exception if the parameter is not a kind_of?(to_be)
- def _pv_kind_of(opts, key, to_be)
- value = _pv_opts_lookup(opts, key)
- unless value.nil?
- passes = false
- Array(to_be).each do |tb|
- passes = true if value.kind_of?(tb)
- end
- unless passes
- raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}."
+ #
+ # List of method names values must respond to.
+ #
+ # Uses value.respond_to?(respond_to) to evaluate. At least one must match
+ # for the value to be valid.
+ #
+ def _pv_respond_to(opts, key, method_name_list)
+ value = _pv_opts_lookup(opts, key)
+ unless value.nil?
+ Array(method_name_list).each do |method_name|
+ unless value.respond_to?(method_name)
+ raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!"
end
end
end
+ end
- # Raise an exception if the parameter does not respond to a given set of methods.
- def _pv_respond_to(opts, key, method_name_list)
- value = _pv_opts_lookup(opts, key)
- unless value.nil?
- Array(method_name_list).each do |method_name|
- unless value.respond_to?(method_name)
- raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!"
+ #
+ # List of things that must not be true about the value.
+ #
+ # Calls `value.<thing>?` All responses must be false for the value to be
+ # valid.
+ # Values which do not respond to <thing>? are considered valid (because if
+ # a value doesn't respond to `:readable?`, then it probably isn't
+ # readable.)
+ #
+ # @example
+ # ```ruby
+ # property :x, cannot_be: [ :nil, :empty ]
+ # x [ 1, 2 ] #=> valid
+ # x 1 #=> valid
+ # x [] #=> invalid
+ # x nil #=> invalid
+ # ```
+ #
+ def _pv_cannot_be(opts, key, predicate_method_base_name)
+ value = _pv_opts_lookup(opts, key)
+ if !value.nil?
+ Array(predicate_method_base_name).each do |method_name|
+ predicate_method = :"#{method_name}?"
+
+ if value.respond_to?(predicate_method)
+ if value.send(predicate_method)
+ raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}"
end
end
end
end
+ end
- # Assert that parameter returns false when passed a predicate method.
- # For example, :cannot_be => :blank will raise a Exceptions::ValidationFailed
- # error value.blank? returns a 'truthy' (not nil or false) value.
- #
- # Note, this will *PASS* if the object doesn't respond to the method.
- # So, to make sure a value is not nil and not blank, you need to do
- # both :cannot_be => :blank *and* :cannot_be => :nil (or :required => true)
- def _pv_cannot_be(opts, key, predicate_method_base_name)
- value = _pv_opts_lookup(opts, key)
- predicate_method = (predicate_method_base_name.to_s + "?").to_sym
-
- if value.respond_to?(predicate_method)
- if value.send(predicate_method)
- raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}"
- end
- end
+ #
+ # The default value for a property.
+ #
+ # When the property is not assigned, this will be used.
+ #
+ # If this is a lazy value, it will either be passed the resource as a value,
+ # or if the lazy proc does not take parameters, it will be run in the
+ # context of the instance with instance_eval.
+ #
+ # @example
+ # ```ruby
+ # property :x, default: 10
+ # ```
+ #
+ # @example
+ # ```ruby
+ # property :x
+ # property :y, default: lazy { x+2 }
+ # ```
+ #
+ # @example
+ # ```ruby
+ # property :x
+ # property :y, default: lazy { |r| r.x+2 }
+ # ```
+ #
+ def _pv_default(opts, key, default_value)
+ value = _pv_opts_lookup(opts, key)
+ if value.nil?
+ default_value = default_value.freeze if !default_value.is_a?(DelayedEvaluator)
+ opts[key] = default_value
end
+ end
- # Assign a default value to a parameter.
- def _pv_default(opts, key, default_value)
- value = _pv_opts_lookup(opts, key)
- if value == nil
- opts[key] = default_value
+ #
+ # List of regexes values that must match.
+ #
+ # Uses regex.match() to evaluate. At least one must match for the value to
+ # be valid.
+ #
+ # `nil` passes regex validation automatically.
+ #
+ # @example
+ # ```ruby
+ # property :x, regex: [ /abc/, /xyz/ ]
+ # ```
+ #
+ def _pv_regex(opts, key, regex)
+ value = _pv_opts_lookup(opts, key)
+ if !value.nil?
+ Array(regex).each do |r|
+ return true if r.match(value.to_s)
end
+ raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}"
end
+ end
- # Check a parameter against a regular expression.
- def _pv_regex(opts, key, regex)
- value = _pv_opts_lookup(opts, key)
- if value != nil
- passes = false
- [ regex ].flatten.each do |r|
- if value != nil
- if r.match(value.to_s)
- passes = true
- end
- end
- end
- unless passes
- raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}"
+ #
+ # List of procs we pass the value to.
+ #
+ # All procs must return true for the value to be valid. If any procs do
+ # not return true, the key will be used for the message: `"Property x's
+ # value :y <message>"`.
+ #
+ # @example
+ # ```ruby
+ # property :x, callbacks: { "is bigger than 10" => proc { |v| v <= 10 }, "is not awesome" => proc { |v| !v.awesome }}
+ # ```
+ #
+ def _pv_callbacks(opts, key, callbacks)
+ raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash)
+ value = _pv_opts_lookup(opts, key)
+ if !value.nil?
+ callbacks.each do |message, zeproc|
+ if zeproc.call(value) != true
+ raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!"
end
end
end
+ end
- # Check a parameter against a hash of proc's.
- def _pv_callbacks(opts, key, callbacks)
- raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash)
- value = _pv_opts_lookup(opts, key)
- if value != nil
- callbacks.each do |message, zeproc|
- if zeproc.call(value) != true
- raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!"
- end
- end
+ #
+ # Allows a parameter to default to the value of the resource name.
+ #
+ # @example
+ # ```ruby
+ # property :x, name_property: true
+ # ```
+ #
+ def _pv_name_property(opts, key, is_name_property=true)
+ if is_name_property
+ if opts[key].nil?
+ opts[key] = self.instance_variable_get("@name")
end
end
+ end
+ alias :_pv_name_attribute :_pv_name_property
- # Allow a parameter to default to @name
- def _pv_name_attribute(opts, key, is_name_attribute=true)
- if is_name_attribute
- if opts[key] == nil
- opts[key] = self.instance_variable_get("@name")
- end
+ #
+ # List of valid things values can be.
+ #
+ # Uses Ruby's `===` to evaluate (is === value). At least one must match
+ # for the value to be valid.
+ #
+ # If a proc is passed, it is instance_eval'd in the resource, passed the
+ # value, and must return a truthy or falsey value.
+ #
+ # @example Class
+ # ```ruby
+ # property :x, String
+ # x 'valid' #=> valid
+ # x 1 #=> invalid
+ # x nil #=> invalid
+ #
+ # @example Value
+ # ```ruby
+ # property :x, [ :a, :b, :c, nil ]
+ # x :a #=> valid
+ # x nil #=> valid
+ # ```
+ #
+ # @example Regex
+ # ```ruby
+ # property :x, /bar/
+ # x 'foobar' #=> valid
+ # x 'foo' #=> invalid
+ # x nil #=> invalid
+ # ```
+ #
+ # @example Proc
+ # ```ruby
+ # property :x, proc { |x| x > y }
+ # property :y, default: 2
+ # x 3 #=> valid
+ # x 1 #=> invalid
+ # ```
+ #
+ # @example PropertyType
+ # ```ruby
+ # type = PropertyType.new(is: String)
+ # property :x, type
+ # x 'foo' #=> valid
+ # x 1 #=> invalid
+ # x nil #=> invalid
+ # ```
+ #
+ # @example RSpec Matcher
+ # ```ruby
+ # include RSpec::Matchers
+ # property :x, a_string_matching /bar/
+ # x 'foobar' #=> valid
+ # x 'foo' #=> invalid
+ # x nil #=> invalid
+ # ```
+ #
+ def _pv_is(opts, key, to_be, raise_error: true)
+ return true if !opts.has_key?(key.to_s) && !opts.has_key?(key.to_sym)
+ value = _pv_opts_lookup(opts, key)
+ to_be = [ to_be ].flatten(1)
+ to_be.each do |tb|
+ if tb.is_a?(Proc)
+ return true if instance_exec(value, &tb)
+ else
+ return true if tb === value
end
end
+
+ if raise_error
+ raise Exceptions::ValidationFailed, "Option #{key} must be one of: #{to_be.join(", ")}! You passed #{value.inspect}."
+ else
+ false
+ end
+ end
+
+ #
+ # Method to mess with a value before it is validated and stored.
+ #
+ # Allows you to transform values into a canonical form that is easy to
+ # work with.
+ #
+ # This is passed the value to transform, and is run in the context of the
+ # instance (so it has access to other resource properties). It must return
+ # the value that will be stored in the instance.
+ #
+ # @example
+ # ```ruby
+ # property :x, Integer, coerce: { |v| v.to_i }
+ # ```
+ #
+ def _pv_coerce(opts, key, coercer)
+ if opts.has_key?(key.to_s)
+ opts[key.to_s] = instance_exec(opts[key], &coercer)
+ elsif opts.has_key?(key.to_sym)
+ opts[key.to_sym] = instance_exec(opts[key], &coercer)
+ end
+ end
end
end
end
-
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index bae7608f5b..8d2532dac4 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -58,8 +58,6 @@ class Chef
include Chef::Mixin::ShellOut
include Chef::Mixin::PowershellOut
- NULL_ARG = Object.new
-
#
# The node the current Chef run is using.
#
@@ -712,6 +710,106 @@ class Chef
provider(arg)
end
+ #
+ # Create a property on this resource class.
+ #
+ # If a superclass has this property, or if this property has already been
+ # defined by this resource, this will *override* the previous value.
+ #
+ # @param name [Symbol] The name of the property.
+ # @param type [Object,Array<Object>] The type(s) of this property.
+ # If present, this is prepended to the `is` validation option.
+ # @param options [Hash<Symbol,Object>] Validation options.
+ # @option options [Object,Array] :is An object, or list of
+ # objects, that must match the value using Ruby's `===` operator
+ # (`options[:is].any? { |v| v === value }`).
+ # @option options [Object,Array] :equal_to An object, or list
+ # of objects, that must be equal to the value using Ruby's `==`
+ # operator (`options[:is].any? { |v| v == value }`)
+ # @option options [Regexp,Array<Regexp>] :regex An object, or
+ # list of objects, that must match the value with `regex.match(value)`.
+ # @option options [Class,Array<Class>] :kind_of A class, or
+ # list of classes, that the value must be an instance of.
+ # @option options [Hash<String,Proc>] :callbacks A hash of
+ # messages -> procs, all of which match the value. The proc must
+ # return a truthy or falsey value (true means it matches).
+ # @option options [Symbol,Array<Symbol>] :respond_to A method
+ # name, or list of method names, the value must respond to.
+ # @option options [Symbol,Array<Symbol>] :cannot_be A property,
+ # or a list of properties, that the value cannot have (such as `:nil` or
+ # `:empty`). The method with a questionmark at the end is called on the
+ # value (e.g. `value.empty?`). If the value does not have this method,
+ # it is considered valid (i.e. if you don't respond to `empty?` we
+ # assume you are not empty).
+ # @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*
+ # be passed to this method until after they are evaluated. Called in the
+ # context of the resource (meaning you can access other properties).
+ # @option options [Boolean] :required `true` if this property
+ # must be present; `false` otherwise. This is checked after the resource
+ # is fully initialized.
+ # @option options [Boolean] :name_property `true` if this
+ # property defaults to the same value as `name`. Equivalent to
+ # `default: lazy { name }`, except that #property_is_set? will
+ # return `true` if the property is set *or* if `name` is set.
+ # @option options [Boolean] :name_attribute Same as `name_property`.
+ # @option options [Object] :default 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).
+ #
+ # @example Bare property
+ # property :x
+ #
+ # @example With just a type
+ # property :x, String
+ #
+ # @example With just options
+ # property :x, default: 'hi'
+ #
+ # @example With type and options
+ # property :x, String, default: 'hi'
+ #
+ def self.property(name, type=NOT_PASSED, **options)
+ name = name.to_sym
+
+ if type != NOT_PASSED
+ if options[:is]
+ options[:is] = ([ type ] + [ options[:is] ]).flatten(1)
+ else
+ options[:is] = type
+ end
+ end
+
+ define_method(name) do |value=NOT_PASSED|
+ set_or_return(name, value, options)
+ end
+ define_method("#{name}=") do |value|
+ set_or_return(name, value, options)
+ end
+ end
+
+ #
+ # Whether this property has been set (or whether it has a default that has
+ # been retrieved).
+ #
+ def property_is_set?(name)
+ name = name.to_sym
+ instance_variable_defined?("@#{name}")
+ end
+
+ #
+ # Create a lazy value for assignment to a default value.
+ #
+ # @param block The block to run when the value is retrieved.
+ #
+ # @return [Chef::DelayedEvaluator] The lazy value
+ #
+ def self.lazy(&block)
+ DelayedEvaluator.new(&block)
+ end
+
# Set or return the list of "state attributes" implemented by the Resource
# subclass. State attributes are attributes that describe the desired state
# of the system, such as file permissions or ownership. In general, state
@@ -777,8 +875,8 @@ class Chef
# have.
#
attr_accessor :allowed_actions
- def allowed_actions(value=NULL_ARG)
- if value != NULL_ARG
+ def allowed_actions(value=NOT_PASSED)
+ if value != NOT_PASSED
self.allowed_actions = value
end
@allowed_actions
@@ -912,9 +1010,9 @@ class Chef
#
# @return [Symbol] The name of this resource type (e.g. `:execute`).
#
- def self.resource_name(name=NULL_ARG)
+ def self.resource_name(name=NOT_PASSED)
# Setter
- if name != NULL_ARG
+ if name != NOT_PASSED
remove_canonical_dsl
# Set the resource_name and call provides
@@ -1004,8 +1102,8 @@ class Chef
#
# @return [Symbol,Array<Symbol>] The default actions for the resource.
#
- def self.default_action(action_name=NULL_ARG)
- unless action_name.equal?(NULL_ARG)
+ def self.default_action(action_name=NOT_PASSED)
+ unless action_name.equal?(NOT_PASSED)
if action_name.is_a?(Array)
@default_action = action_name.map { |arg| arg.to_sym }
else
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index ef3c2b5bba..443e0ed819 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -74,13 +74,7 @@ class Chef
resource_class
end
- # Define an attribute on this resource, including optional validation
- # parameters.
- def attribute(attr_name, validation_opts={})
- define_method(attr_name) do |arg=nil|
- set_or_return(attr_name.to_sym, arg, validation_opts)
- end
- end
+ alias :attribute :property
# Adds +action_names+ to the list of valid actions for this resource.
# Does not include superclass's action list when appending.