class Chef::Node

Attributes

override_runlist[RW]
recipe_list[RW]
run_context[RW]

RunContext will set itself as #run_context via this setter when initialized. This is needed so DSL::IncludeAttribute (in particular, include_recipe) can access the #run_context to determine if an attributes file has been seen yet.

run_state[RW]

Public Class Methods

build(node_name) click to toggle source
# File lib/chef/node.rb, line 499
def self.build(node_name)
  node = new
  node.name(node_name)
  node.chef_environment(Chef::Config[:environment]) unless Chef::Config[:environment].nil? || Chef::Config[:environment].chomp.empty?
  node
end
find_or_create(node_name) click to toggle source
# File lib/chef/node.rb, line 491
def self.find_or_create(node_name)
  load(node_name)
rescue Net::HTTPServerException => e
  raise unless e.response.code == '404'
  node = build(node_name)
  node.create
end
json_create(o) click to toggle source

Create a Chef::Node from JSON

# File lib/chef/node.rb, line 449
def self.json_create(o)
  node = new
  node.name(o["name"])
  node.chef_environment(o["chef_environment"])
  if o.has_key?("attributes")
    node.normal_attrs = o["attributes"]
  end
  node.automatic_attrs = Mash.new(o["automatic"]) if o.has_key?("automatic")
  node.normal_attrs = Mash.new(o["normal"]) if o.has_key?("normal")
  node.default_attrs = Mash.new(o["default"]) if o.has_key?("default")
  node.override_attrs = Mash.new(o["override"]) if o.has_key?("override")

  if o.has_key?("run_list")
    node.run_list.reset!(o["run_list"])
  else
    o["recipes"].each { |r| node.recipes << r }
  end
  node
end
list(inflate=false) click to toggle source
# File lib/chef/node.rb, line 479
def self.list(inflate=false)
  if inflate
    response = Hash.new
    Chef::Search::Query.new.search(:node) do |n|
      response[n.name] = n unless n.nil?
    end
    response
  else
    Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("nodes")
  end
end
list_by_environment(environment, inflate=false) click to toggle source
# File lib/chef/node.rb, line 469
def self.list_by_environment(environment, inflate=false)
  if inflate
    response = Hash.new
    Chef::Search::Query.new.search(:node, "chef_environment:#{environment}") {|n| response[n.name] = n unless n.nil?}
    response
  else
    Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("environments/#{environment}/nodes")
  end
end
load(name) click to toggle source

Load a node by name

# File lib/chef/node.rb, line 507
def self.load(name)
  Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("nodes/#{name}")
end
new() click to toggle source

Create a new Chef::Node object.

# File lib/chef/node.rb, line 63
def initialize
  @name = nil

  @chef_environment = '_default'
  @primary_runlist = Chef::RunList.new
  @override_runlist = Chef::RunList.new

  @attributes = Chef::Node::Attribute.new({}, {}, {}, {})

  @run_state = {}
end

Public Instance Methods

<=>(other_node) click to toggle source
# File lib/chef/node.rb, line 543
def <=>(other_node)
  self.name <=> other_node.name
end
[](attrib) click to toggle source

Return an attribute of this node. Returns nil if the attribute is not found.

# File lib/chef/node.rb, line 121
def [](attrib)
  attributes[attrib]
end
apply_expansion_attributes(expansion) click to toggle source

Apply the default and overrides attributes from the expansion passed in, which came from roles.

# File lib/chef/node.rb, line 376
def apply_expansion_attributes(expansion)
  loaded_environment = if chef_environment == "_default"
                         Chef::Environment.new.tap {|e| e.name("_default")}
                       else
                         Chef::Environment.load(chef_environment)
                       end

  attributes.env_default = loaded_environment.default_attributes
  attributes.env_override = loaded_environment.override_attributes

  attribute.role_default = expansion.default_attrs
  attributes.role_override = expansion.override_attrs
end
attribute()
Alias for: attributes
attribute?(attrib) click to toggle source

Return true if this Node has a given attribute, false if not. Takes either a symbol or a string.

Only works on the top level. Preferred way is to use the normal [] style lookup and call attribute?()

# File lib/chef/node.rb, line 222
def attribute?(attrib)
  attributes.attribute?(attrib)
end
attributes() click to toggle source
# File lib/chef/node.rb, line 113
def attributes
  @attributes
end
Also aliased as: attribute, construct_attributes
automatic_attrs() click to toggle source
# File lib/chef/node.rb, line 209
def automatic_attrs
  attributes.automatic
end
automatic_attrs=(new_values) click to toggle source
# File lib/chef/node.rb, line 213
def automatic_attrs=(new_values)
  attributes.automatic = new_values
end
chef_environment(arg=nil) click to toggle source
# File lib/chef/node.rb, line 99
def chef_environment(arg=nil)
  set_or_return(
    :chef_environment,
    arg,
    { :regex => /^[\-[:alnum:]_]+$/, :kind_of => String }
  )
end
Also aliased as: environment
chef_environment=(environment) click to toggle source
# File lib/chef/node.rb, line 107
def chef_environment=(environment)
  chef_environment(environment)
end
chef_server_rest() click to toggle source
# File lib/chef/node.rb, line 80
def chef_server_rest
  Chef::REST.new(Chef::Config[:chef_server_url])
end
construct_attributes()
Alias for: attributes
consume_attributes(attrs) click to toggle source

Consumes the combined #run_list and other attributes in attrs

# File lib/chef/node.rb, line 307
def consume_attributes(attrs)
  normal_attrs_to_merge = consume_run_list(attrs)
  Chef::Log.debug("Applying attributes from json file")
  self.normal_attrs = Chef::Mixin::DeepMerge.merge(normal_attrs,normal_attrs_to_merge)
  self.tags # make sure they're defined
end
consume_external_attrs(ohai_data, json_cli_attrs) click to toggle source

Consume data from ohai and Attributes provided as JSON on the command line.

# File lib/chef/node.rb, line 294
def consume_external_attrs(ohai_data, json_cli_attrs)
  Chef::Log.debug("Extracting run list from JSON attributes provided on command line")
  consume_attributes(json_cli_attrs)

  self.automatic_attrs = ohai_data

  platform, version = Chef::Platform.find_platform_and_version(self)
  Chef::Log.debug("Platform is #{platform} version #{version}")
  self.automatic[:platform] = platform
  self.automatic[:platform_version] = version
end
consume_run_list(attrs) click to toggle source

Extracts the run list from attrs and applies it. Returns the remaining attributes

# File lib/chef/node.rb, line 329
def consume_run_list(attrs)
  attrs = attrs ? attrs.dup : {}
  if new_run_list = attrs.delete("recipes") || attrs.delete("run_list")
    if attrs.key?("recipes") || attrs.key?("run_list")
      raise Chef::Exceptions::AmbiguousRunlistSpecification, "please set the node's run list using the 'run_list' attribute only."
    end
    Chef::Log.info("Setting the run_list to #{new_run_list.inspect} from CLI options")
    run_list(new_run_list)
  end
  attrs
end
create() click to toggle source

Create the node via the REST API

# File lib/chef/node.rb, line 534
def create
  chef_server_rest.post_rest("nodes", data_for_save)
  self
end
default() click to toggle source

Set a default of this node, but auto-vivify any Mashes that might be missing

# File lib/chef/node.rb, line 144
def default
  attributes.set_unless_value_present = false
  attributes.default
end
default!() click to toggle source

Set a force default attribute. Intermediate mashes will be created by auto-vivify if necessary.

# File lib/chef/node.rb, line 151
def default!
  attributes.set_unless_value_present = false
  attributes.default!
end
default_attrs() click to toggle source
# File lib/chef/node.rb, line 193
def default_attrs
  attributes.default
end
default_attrs=(new_values) click to toggle source
# File lib/chef/node.rb, line 197
def default_attrs=(new_values)
  attributes.default = new_values
end
default_unless() click to toggle source

Set a default attribute of this node, auto-vivifying any mashes that are missing, but if the final value already exists, don't set it

# File lib/chef/node.rb, line 158
def default_unless
  attributes.set_unless_value_present = true
  attributes.default
end
destroy() click to toggle source

Remove this node via the REST API

# File lib/chef/node.rb, line 512
def destroy
  chef_server_rest.delete_rest("nodes/#{name}")
end
display_hash() click to toggle source
# File lib/chef/node.rb, line 405
def display_hash
  display = {}
  display["name"]             = name
  display["chef_environment"] = chef_environment
  display["automatic"]        = automatic_attrs
  display["normal"]           = normal_attrs
  display["default"]          = attributes.combined_default
  display["override"]         = attributes.combined_override
  display["run_list"]         = run_list.run_list
  display
end
each(&block) click to toggle source

Yield each key of the top level to the block.

# File lib/chef/node.rb, line 227
def each(&block)
  attributes.each(&block)
end
each_attribute(&block) click to toggle source

Iterates over each attribute, passing the attribute and value to the block.

# File lib/chef/node.rb, line 232
def each_attribute(&block)
  attributes.each_attribute(&block)
end
environment(arg=nil)
Alias for: chef_environment
expand!(data_source = 'server') click to toggle source

Expands the node's run list and sets the default and override attributes. Also applies stored attributes (from json provided on the command line)

Returns the fully-expanded list of recipes, a RunListExpansion.

# File lib/chef/node.rb, line 360
def expand!(data_source = 'server')
  expansion = run_list.expand(chef_environment, data_source)
  raise Chef::Exceptions::MissingRole, expansion if expansion.errors?

  self.tags # make sure they're defined

  automatic_attrs[:recipes] = expansion.recipes
  automatic_attrs[:roles] = expansion.roles

  apply_expansion_attributes(expansion)

  expansion
end
for_json() click to toggle source
# File lib/chef/node.rb, line 422
def for_json
  result = {
    "name" => name,
    "chef_environment" => chef_environment,
    'json_class' => self.class.name,
    "automatic" => attributes.automatic,
    "normal" => attributes.normal,
    "chef_type" => "node",
    "default" => attributes.combined_default,
    "override" => attributes.combined_override,
    #Render correctly for run_list items so malformed json does not result
    "run_list" => @primary_runlist.run_list.map { |item| item.to_s }
  }
  result
end
loaded_recipe(cookbook, recipe) click to toggle source

used by include_recipe to add recipes to the expanded #run_list to be saved back to the node and be searchable

# File lib/chef/node.rb, line 254
def loaded_recipe(cookbook, recipe)
  fully_qualified_recipe = "#{cookbook}::#{recipe}"
  automatic_attrs[:recipes] << fully_qualified_recipe unless Array(self[:recipes]).include?(fully_qualified_recipe)
end
method_missing(symbol, *args) click to toggle source

Only works for attribute fetches, setting is no longer supported

# File lib/chef/node.rb, line 237
def method_missing(symbol, *args)
  attributes.send(symbol, *args)
end
name(arg=nil) click to toggle source

Set the name of this Node, or return the current name.

# File lib/chef/node.rb, line 85
def name(arg=nil)
  if arg != nil
    validate(
             {:name => arg },
             {:name => { :kind_of => String,
                 :cannot_be => :blank,
                 :regex => /^[\-[:alnum:]_:.]+$/}
             })
    @name = arg
  else
    @name
  end
end
node() click to toggle source

Used by DSL

# File lib/chef/node.rb, line 76
def node
  self
end
normal() click to toggle source

Set a normal attribute of this node, but auto-vivify any Mashes that might be missing

# File lib/chef/node.rb, line 127
def normal
  attributes.set_unless_value_present = false
  attributes.normal
end
Also aliased as: set
normal_attrs() click to toggle source
# File lib/chef/node.rb, line 201
def normal_attrs
  attributes.normal
end
normal_attrs=(new_values) click to toggle source
# File lib/chef/node.rb, line 205
def normal_attrs=(new_values)
  attributes.normal = new_values
end
normal_unless() click to toggle source

Set a normal attribute of this node, auto-vivifying any mashes that are missing, but if the final value already exists, don't set it

# File lib/chef/node.rb, line 136
def normal_unless
  attributes.set_unless_value_present = true
  attributes.normal
end
Also aliased as: set_unless
override() click to toggle source

Set an override attribute of this node, but auto-vivify any Mashes that might be missing

# File lib/chef/node.rb, line 165
def override
  attributes.set_unless_value_present = false
  attributes.override
end
override!() click to toggle source

Set a force override attribute. Intermediate mashes will be created by auto-vivify if needed.

# File lib/chef/node.rb, line 172
def override!
  attributes.set_unless_value_present = false
  attributes.override!
end
override_attrs() click to toggle source
# File lib/chef/node.rb, line 185
def override_attrs
 attributes.override
end
override_attrs=(new_values) click to toggle source
# File lib/chef/node.rb, line 189
def override_attrs=(new_values)
  attributes.override = new_values
end
override_unless() click to toggle source

Set an override attribute of this node, auto-vivifying any mashes that are missing, but if the final value already exists, don't set it

# File lib/chef/node.rb, line 179
def override_unless
  attributes.set_unless_value_present = true
  attributes.override
end
primary_runlist() click to toggle source
# File lib/chef/node.rb, line 264
def primary_runlist
  @primary_runlist
end
recipe?(recipe_name) click to toggle source

Returns true if this Node expects a given recipe, false if not.

First, the run list is consulted to see whether the recipe is explicitly included. If it's not there, it looks in `node`, which is populated when the #run_list is expanded

NOTE: It's used by cookbook authors

# File lib/chef/node.rb, line 248
def recipe?(recipe_name)
  run_list.include?(recipe_name) || Array(self[:recipes]).include?(recipe_name)
end
reset_defaults_and_overrides() click to toggle source

Clear defaults and overrides, so that any deleted attributes between runs are still gone.

# File lib/chef/node.rb, line 343
def reset_defaults_and_overrides
  self.default.clear
  self.override.clear
end
role?(role_name) click to toggle source

Returns true if this Node expects a given role, false if not.

# File lib/chef/node.rb, line 260
def role?(role_name)
  run_list.include?("role[#{role_name}]")
end
run_list(*args) click to toggle source

Returns an Array of roles and recipes, in the order they will be applied. If you call it with arguments, they will become the new list of roles and recipes.

# File lib/chef/node.rb, line 278
def run_list(*args)
  rl = select_run_list
  args.length > 0 ? rl.reset!(args) : rl
end
run_list=(list) click to toggle source
# File lib/chef/node.rb, line 283
def run_list=(list)
  rl = select_run_list
  rl = list
end
run_list?(item) click to toggle source

Returns true if this Node expects a given role, false if not.

# File lib/chef/node.rb, line 289
def run_list?(item)
  run_list.detect { |r| r == item } ? true : false
end
save() click to toggle source

Save this node via the REST API

# File lib/chef/node.rb, line 517
def save
  # Try PUT. If the node doesn't yet exist, PUT will return 404,
  # so then POST to create.
  begin
    if Chef::Config[:why_run]
      Chef::Log.warn("In whyrun mode, so NOT performing node save.")
    else
      chef_server_rest.put_rest("nodes/#{name}", data_for_save)
    end
  rescue Net::HTTPServerException => e
    raise e unless e.response.code == "404"
    chef_server_rest.post_rest("nodes", data_for_save)
  end
  self
end
select_run_list() click to toggle source
# File lib/chef/node.rb, line 272
def select_run_list
  @override_runlist.empty? ? @primary_runlist : @override_runlist
end
set()
Alias for: normal
set_unless()
Alias for: normal_unless
tag(*tags) click to toggle source
# File lib/chef/node.rb, line 320
def tag(*tags)
  tags.each do |tag|
    self.normal[:tags].push(tag.to_s) unless self[:tags].include? tag.to_s
  end

  self[:tags]
end
tags() click to toggle source

Lazy initializer for tags attribute

# File lib/chef/node.rb, line 315
def tags
  normal[:tags] = [] unless attribute?(:tags)
  normal[:tags]
end
to_hash() click to toggle source

Transform the node to a Hash

# File lib/chef/node.rb, line 391
def to_hash
  index_hash = Hash.new
  index_hash["chef_type"] = "node"
  index_hash["name"] = name
  index_hash["chef_environment"] = chef_environment
  attribute.each do |key, value|
    index_hash[key] = value
  end
  index_hash["recipe"] = run_list.recipe_names if run_list.recipe_names.length > 0
  index_hash["role"] = run_list.role_names if run_list.role_names.length > 0
  index_hash["run_list"] = run_list.run_list if run_list.run_list.length > 0
  index_hash
end
to_json(*a) click to toggle source

Serialize this object as a hash

# File lib/chef/node.rb, line 418
def to_json(*a)
  for_json.to_json(*a)
end
to_s() click to toggle source
# File lib/chef/node.rb, line 539
def to_s
  "node[#{name}]"
end
update_from!(o) click to toggle source
# File lib/chef/node.rb, line 438
def update_from!(o)
  run_list.reset!(o.run_list)
  self.automatic_attrs = o.automatic_attrs
  self.normal_attrs = o.normal_attrs
  self.override_attrs = o.override_attrs
  self.default_attrs = o.default_attrs
  chef_environment(o.chef_environment)
  self
end

Private Instance Methods

data_for_save() click to toggle source
# File lib/chef/node.rb, line 549
def data_for_save
  data = for_json
  ["automatic", "default", "normal", "override"].each do |level|
    whitelist_config_option = "#{level}_attribute_whitelist".to_sym
    whitelist = Chef::Config[whitelist_config_option]
    unless whitelist.nil? # nil => save everything
      Chef::Log.info("Whitelisting #{level} node attributes for save.")
      data[level] = Chef::Whitelist.filter(data[level], whitelist)
    end
  end
  data
end