Parent

Included Modules

Class/Module Index [+]

Quicksearch

Chef::Node::Attribute

Constants

HIDDEN_ATTRIBUES

Attributes

auto_vivifiy_on_read[RW]
automatic[RW]
current_automatic[RW]
current_default[RW]
current_normal[RW]
current_override[RW]
default[RW]
normal[RW]
override[RW]
set_type[RW]
set_unless_value_present[RW]

Public Class Methods

new(normal, default, override, automatic, state=[]) click to toggle source
# File lib/chef/node/attribute.rb, line 42
def initialize(normal, default, override, automatic, state=[])
  @normal = normal
  @current_normal = normal
  @default = default
  @current_default = default
  @override = override
  @current_override = override
  @automatic = automatic
  @current_automatic = automatic
  @current_nesting_level = state
  @auto_vivifiy_on_read = false
  @set_unless_value_present = false
  @set_type = nil
  @has_been_read = false
end

Public Instance Methods

[](key) click to toggle source
# File lib/chef/node/attribute.rb, line 89
def [](key)
  @current_nesting_level << key

  # We set this to so that we can cope with ||= as a setting.
  # See the comments in []= for more details.
  @has_been_read = true

  # If we have a set type, our destiny is to write
  if @set_type
    a_value = @set_type == :automatic ? value_or_descend(current_automatic, key, auto_vivifiy_on_read) : nil
    o_value = @set_type == :override ? value_or_descend(current_override, key, auto_vivifiy_on_read) : nil
    n_value = @set_type == :normal ? value_or_descend(current_normal, key, auto_vivifiy_on_read) : nil
    d_value = @set_type == :default ? value_or_descend(current_default, key, auto_vivifiy_on_read) : nil

    determine_value(a_value, o_value, n_value, d_value)
  # Our destiny is only to read, so we get the full list.
  else
    a_value = value_or_descend(current_automatic, key)
    o_value = value_or_descend(current_override, key)
    n_value = value_or_descend(current_normal, key)
    d_value = value_or_descend(current_default, key)

    determine_value(a_value, o_value, n_value, d_value)
  end
end
[]=(key, value) click to toggle source
# File lib/chef/node/attribute.rb, line 319
def []=(key, value)
  # If we don't have one, then we'll pretend we're normal
  if @set_type.nil?
    @set_type = :normal
    warning=Setting attributes without specifying a precedence is deprecated and will beremoved in Chef 11.0. To set attributes at normal precedence, change code like:`node["key"] = "value"` # Not thisto:`node.set["key"] = "value"` # ThisCalled from:

    warning_with_line_nrs = caller[0...3].inject(warning) do |msg, source_line|
      msg << "  #{source_line}\n"
    end

    Chef::Log.warn(warning_with_line_nrs) if Chef::Config[:chef11_deprecation_warnings]
  end

  if set_unless_value_present
    if get_value(set_type_hash, key) != nil
      Chef::Log.debug("Not setting #{@current_nesting_level.join("/")}/#{key} to #{value.inspect} because it has a #{@set_type} value already")
      return false
    end
  end

  # If we have been read, and the key we are writing is the same
  # as our parent, we have most like been ||='ed.  So we need to
  # just rewind a bit.
  #
  # In practice, these objects are single use - this is just
  # supporting one more single-use style.
  @current_nesting_level.pop if @has_been_read && @current_nesting_level.last == key

  set_value(set_type_hash, key, value)
  value
end
attribute() click to toggle source
# File lib/chef/node/attribute.rb, line 58
def attribute
  normal
end
attribute=(value) click to toggle source
# File lib/chef/node/attribute.rb, line 62
def attribute=(value)
  normal = value
end
attribute?(key) click to toggle source
Alias for: has_key?
auto_vivifiy(data_hash, key) click to toggle source
# File lib/chef/node/attribute.rb, line 388
def auto_vivifiy(data_hash, key)
  if data_hash.has_key?(key)
    unless data_hash[key].respond_to?(:has_key?)
      raise ArgumentError, "You tried to set a nested key, where the parent is not a hash-like object: #{@current_nesting_level.join("/")}/#{key} " unless auto_vivifiy_on_read
    end
  else
    data_hash[key] = Mash.new
  end
  data_hash
end
auto_vivifiy_on_read?() click to toggle source
# File lib/chef/node/attribute.rb, line 384
def auto_vivifiy_on_read?
  auto_vivifiy_on_read
end
component_has_key?(component_attrs,key) click to toggle source
# File lib/chef/node/attribute.rb, line 488
def component_has_key?(component_attrs,key)
  # get the Hash-like object at the current nesting level:
  nested_attrs = value_at_current_nesting(component_attrs, key)
  nested_attrs.respond_to?(:key?) && nested_attrs.key?(key)
end
delete(key) click to toggle source
# File lib/chef/node/attribute.rb, line 470
def delete(key)
  [@automatic, @override, @normal, @default].inject(nil) do |return_value, attrs|
    deleted_value = delete_from_component(attrs, key)
    return_value || deleted_value
  end
end
delete_from_component(component_attrs, key) click to toggle source
# File lib/chef/node/attribute.rb, line 477
def delete_from_component(component_attrs, key)
  # get the Hash-like object at the current nesting level:
  nested_attrs = value_at_current_nesting(component_attrs, key)

  if nested_attrs.respond_to?(:delete)
    nested_attrs.delete(key)
  else
    nil
  end
end
determine_value(a_value, o_value, n_value, d_value) click to toggle source
# File lib/chef/node/attribute.rb, line 289
def determine_value(a_value, o_value, n_value, d_value)
  if hash_and_not_cna?(a_value)
    value = {}
    value = Chef::Mixin::DeepMerge.merge(value, d_value) if hash_and_not_cna?(d_value)
    value = Chef::Mixin::DeepMerge.merge(value, n_value) if hash_and_not_cna?(n_value)
    value = Chef::Mixin::DeepMerge.merge(value, o_value) if hash_and_not_cna?(o_value)
    value = Chef::Mixin::DeepMerge.merge(value, a_value)
    value
  elsif hash_and_not_cna?(o_value)
    value = {}
    value = Chef::Mixin::DeepMerge.merge(value, d_value) if hash_and_not_cna?(d_value)
    value = Chef::Mixin::DeepMerge.merge(value, n_value) if hash_and_not_cna?(n_value)
    value = Chef::Mixin::DeepMerge.merge(value, o_value)
    value
  elsif hash_and_not_cna?(n_value)
    value = {}
    value = Chef::Mixin::DeepMerge.merge(value, d_value) if hash_and_not_cna?(d_value)
    value = Chef::Mixin::DeepMerge.merge(value, n_value)
    value
  elsif hash_and_not_cna?(d_value)
    d_value
  else
    return a_value if ! a_value.nil?
    return o_value if ! o_value.nil?
    return n_value if ! n_value.nil?
    return d_value if ! d_value.nil?
    return nil
  end
end
each(&block) click to toggle source
# File lib/chef/node/attribute.rb, line 128
def each(&block)
  get_keys.each do |key|
    value = determine_value(
      get_value(automatic, key),
      get_value(override, key),
      get_value(normal, key),
      get_value(default, key)
    )
    block.call([key, value])
  end
end
each_attribute(&block) click to toggle source
# File lib/chef/node/attribute.rb, line 152
def each_attribute(&block)
  get_keys.each do |key|
    value = determine_value(
      get_value(automatic, key),
      get_value(override, key),
      get_value(normal, key),
      get_value(default, key)
    )
    block.call(key, value)
  end
end
each_key(&block) click to toggle source
# File lib/chef/node/attribute.rb, line 164
def each_key(&block)
  get_keys.each do |key|
    block.call(key)
  end
end
each_pair(&block) click to toggle source
# File lib/chef/node/attribute.rb, line 140
def each_pair(&block)
  get_keys.each do |key|
    value = determine_value(
      get_value(automatic, key),
      get_value(override, key),
      get_value(normal, key),
      get_value(default, key)
    )
    block.call(key, value)
  end
end
each_value(&block) click to toggle source
# File lib/chef/node/attribute.rb, line 170
def each_value(&block)
  get_keys.each do |key|
    value = determine_value(
      get_value(automatic, key),
      get_value(override, key),
      get_value(normal, key),
      get_value(default, key)
    )
    block.call(value)
  end
end
empty?() click to toggle source
# File lib/chef/node/attribute.rb, line 182
def empty?
  get_keys.empty?
end
fetch(key, default_value=nil, &block) click to toggle source
# File lib/chef/node/attribute.rb, line 186
def fetch(key, default_value=nil, &block)
  if get_keys.include? key
    determine_value(
      get_value(automatic, key),
      get_value(override, key),
      get_value(normal, key),
      get_value(default, key)
    )
  elsif default_value
    default_value
  elsif block_given?
    block.call(key)
  else
    raise IndexError, "Key #{key} does not exist"
  end
end
get_keys() click to toggle source
# File lib/chef/node/attribute.rb, line 242
def get_keys
  keys
end
get_value(data_hash, key) click to toggle source
# File lib/chef/node/attribute.rb, line 258
def get_value(data_hash, key)
  last = nil

  if @current_nesting_level.length == 0
    if data_hash.has_key?(key) && ! data_hash[key].nil?
      return data_hash[key]
    else
      return nil
    end
  end

  0.upto(@current_nesting_level.length) do |i|
    if i == 0
      last = auto_vivifiy(data_hash, @current_nesting_level[i])
    elsif i == @current_nesting_level.length
      fk = last[@current_nesting_level[i - 1]]
      if fk.has_key?(key) && ! fk[key].nil?
        return fk[key]
      else
        return nil
      end
    else
      last = auto_vivifiy(last[@current_nesting_level[i - 1]], @current_nesting_level[i])
    end
  end
end
has_key?(key) click to toggle source
# File lib/chef/node/attribute.rb, line 115
def has_key?(key)
  return true if component_has_key?(@default,key)
  return true if component_has_key?(@automatic,key)
  return true if component_has_key?(@normal,key)
  return true if component_has_key?(@override,key)
  false
end
Also aliased as: attribute?, include?, key?, member?
has_value?(value) click to toggle source
# File lib/chef/node/attribute.rb, line 217
def has_value?(value)
  self.any? do |k,v|
    value == v
  end
end
Also aliased as: value?
hash_and_not_cna?(to_check) click to toggle source
# File lib/chef/node/attribute.rb, line 285
def hash_and_not_cna?(to_check)
  (! to_check.kind_of?(Chef::Node::Attribute)) && to_check.respond_to?(:has_key?)
end
include?(key) click to toggle source
Alias for: has_key?
index(value) click to toggle source
# File lib/chef/node/attribute.rb, line 225
def index(value)
  index = self.find do |h|
    value == h[1]
  end
  index.first if index.is_a? Array || nil
end
inspect() click to toggle source
# File lib/chef/node/attribute.rb, line 453
def inspect
  determine_value(current_automatic, current_override, current_normal, current_default)

  "#<#{self.class} " << instance_variables.map{|iv|
    iv.to_s + '=' + (HIDDEN_ATTRIBUES.include?(iv.to_sym) ? "{...}" : instance_variable_get(iv).inspect)
  }.join(', ') << ">"
end
key?(key) click to toggle source
Alias for: has_key?
keys() click to toggle source
# File lib/chef/node/attribute.rb, line 246
def keys
  tkeys = current_automatic ? current_automatic.keys : []
  [ current_override, current_normal, current_default ].each do |attr_hash|
    if attr_hash
      attr_hash.keys.each do |key|
        tkeys << key unless tkeys.include?(key)
      end
    end
  end
  tkeys
end
kind_of?(klass) click to toggle source

Writing this method hurts me a little bit.

TODO: Refactor all this stuff so this kind of horror is no longer needed

We have invented a new kind of duck-typing, we call it Madoff typing. We just lie and hope we die before you recognize our scheme. :)

# File lib/chef/node/attribute.rb, line 209
def kind_of?(klass)
  if klass == Hash || klass == Mash || klass == Chef::Node::Attribute
    true
  else
    false
  end
end
length() click to toggle source
Alias for: size
member?(key) click to toggle source
Alias for: has_key?
method_missing(symbol, *args) click to toggle source

Fetches or sets the value, depending on if any arguments are given.

Fetching

If no arguments are given, fetches the value:

node.network
=> {network data}

Getters will find either a string or symbol key.

Setting

If arguments are given, a value will be set. Both normal setter and DSL style setters are allowed:

node.foo = "bar"
node.foo("bar")

Both set node = "bar"

# File lib/chef/node/attribute.rb, line 435
def method_missing(symbol, *args)
  if args.empty?
    if key?(symbol)
      self[symbol]
    elsif key?(symbol.to_s)
      self[symbol.to_s]
    elsif auto_vivifiy_on_read?
      self[symbol] = Mash.new
      self[symbol]
    else
      raise ArgumentError, "Attribute #{symbol} is not defined!" unless auto_vivifiy_on_read
    end
  else
    key_to_set = symbol.to_s[/^(.+)=$/, 1] || symbol
    self[key_to_set] = (args.length == 1 ? args[0] : args)
  end
end
reset() click to toggle source

Reset our internal current_nesting_level to the top of every tree

# File lib/chef/node/attribute.rb, line 80
def reset
  @current_normal = @normal
  @current_default = @default
  @current_override = @override
  @current_automatic = @automatic
  @has_been_read = false
  @current_nesting_level = []
end
set_type_hash() click to toggle source
# File lib/chef/node/attribute.rb, line 66
def set_type_hash
  case @set_type
  when :normal
    @normal
  when :override
    @override
  when :default
    @default
  when :automatic
    @automatic
  end
end
set_value(data_hash, key, value) click to toggle source
# File lib/chef/node/attribute.rb, line 359
def set_value(data_hash, key, value)
  last = nil

  # If there is no current_nesting_level, just set the value
  if @current_nesting_level.length == 0
    data_hash[key] = value
    return data_hash
  end

  # Walk all the previous places we have been
  0.upto(@current_nesting_level.length) do |i|
    # If we are the first, we are top level, and should vivifiy the data_hash
    if i == 0
      last = auto_vivifiy(data_hash, @current_nesting_level[i])
    # If we are one past the last current_nesting_level, we are adding a key to that hash with a value
    elsif i == @current_nesting_level.length
      last[@current_nesting_level[i - 1]][key] = value
    # Otherwise, we're auto-vivifiy-ing an interim mash
    else
      last = auto_vivifiy(last[@current_nesting_level[i - 1]], @current_nesting_level[i])
    end
  end
  data_hash
end
size() click to toggle source
# File lib/chef/node/attribute.rb, line 236
def size
  self.collect{}.length
end
Also aliased as: length
to_hash() click to toggle source
# File lib/chef/node/attribute.rb, line 461
def to_hash
  result = determine_value(current_automatic, current_override, current_normal, current_default)
  if result.class == Hash
    result
  else
    result.to_hash
  end
end
value?(value) click to toggle source
Alias for: has_value?
value_at_current_nesting(component_attrs, key) click to toggle source
# File lib/chef/node/attribute.rb, line 494
def value_at_current_nesting(component_attrs, key)
  @current_nesting_level.inject(component_attrs) do |subtree, intermediate_key|
    # if the intermediate value isn't a hash or doesn't have the intermediate key,
    # it can't have the bottom-level key we're looking for.
    (subtree.respond_to?(:key?) && subtree[intermediate_key]) or (return false)
  end
end
value_or_descend(data_hash, key, auto_vivifiy=false) click to toggle source
# File lib/chef/node/attribute.rb, line 399
def value_or_descend(data_hash, key, auto_vivifiy=false)
  if auto_vivifiy
    hash_to_vivifiy = auto_vivifiy(data_hash, key)
    data_hash[key] = hash_to_vivifiy[key]
  else
    return nil if data_hash == nil
    return nil unless data_hash.has_key?(key)
  end

  if data_hash[key].respond_to?(:has_key?)
    cna = Chef::Node::Attribute.new(@normal, @default, @override, @automatic, @current_nesting_level)
    cna.current_normal = current_normal.nil? ? Mash.new : current_normal[key]
    cna.current_default   = current_default.nil? ? Mash.new : current_default[key]
    cna.current_override  = current_override.nil? ? Mash.new : current_override[key]
    cna.current_automatic  = current_automatic.nil? ? Mash.new : current_automatic[key]
    cna.auto_vivifiy_on_read = auto_vivifiy_on_read
    cna.set_unless_value_present = set_unless_value_present
    cna.set_type = set_type
    cna
  else
    data_hash[key]
  end
end
values() click to toggle source
# File lib/chef/node/attribute.rb, line 232
def values
  self.collect { |h| h[1] }
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.