TODO: 5/18/2010 cw/timh. cookbook_collection should be removed from here and for any place it's needed, it should be accessed through a Chef::RunContext
# File lib/chef/node.rb, line 595 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].chop.empty? node end
List all the Chef::Node objects in the CouchDB. If inflate is set to true, you will get the full list of all Nodes, fully inflated.
# File lib/chef/node.rb, line 556 def self.cdb_list(inflate=false, couchdb=nil) rs =(couchdb || Chef::CouchDB.new).list("nodes", inflate) lookup = (inflate ? "value" : "key") rs["rows"].collect { |r| r[lookup] } end
# File lib/chef/node.rb, line 539 def self.cdb_list_by_environment(environment, inflate=false, couchdb=nil) rs = (couchdb || Chef::CouchDB.new).get_view("nodes", "by_environment", :include_docs => inflate, :startkey => environment, :endkey => environment) inflate ? rs["rows"].collect {|r| r["doc"]} : rs["rows"].collect {|r| r["value"]} end
Load a node by name from CouchDB
# File lib/chef/node.rb, line 575 def self.cdb_load(name, couchdb=nil) (couchdb || Chef::CouchDB.new).load("node", name) end
Set up our CouchDB design document
# File lib/chef/node.rb, line 646 def self.create_design_document(couchdb=nil) (couchdb || Chef::CouchDB.new).create_design_document("nodes", DESIGN_DOCUMENT) end
# File lib/chef/node.rb, line 579 def self.exists?(nodename, couchdb) begin self.cdb_load(nodename, couchdb) rescue Chef::Exceptions::CouchDBNotFound nil end end
# File lib/chef/node.rb, line 587 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
Create a Chef::Node from JSON
# File lib/chef/node.rb, line 516 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.couchdb_rev = o["_rev"] if o.has_key?("_rev") node.couchdb_id = o["_id"] if o.has_key?("_id") node.index_id = node.couchdb_id node end
# File lib/chef/node.rb, line 562 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
# File lib/chef/node.rb, line 544 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 a node by name
# File lib/chef/node.rb, line 603 def self.load(name) Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("nodes/#{name}") end
Create a new Chef::Node object.
# File lib/chef/node.rb, line 157 def initialize(couchdb=nil) @name = nil @chef_environment = '_default' @normal_attrs = Mash.new @override_attrs = Mash.new @default_attrs = Mash.new @automatic_attrs = Mash.new @run_list = Chef::RunList.new @couchdb_rev = nil @couchdb_id = nil @couchdb = couchdb || Chef::CouchDB.new @run_state = { :template_cache => Hash.new, :seen_recipes => Hash.new, :seen_attributes => Hash.new } # TODO: 5/20/2010 need this here as long as other objects try to access # the cookbook collection via Node, otherwise get NoMethodError on nil. @cookbook_collection = CookbookCollection.new end
Return an attribute of this node. Returns nil if the attribute is not found.
# File lib/chef/node.rb, line 250 def [](attrib) construct_attributes[attrib] end
Set an attribute of this node
# File lib/chef/node.rb, line 255 def []=(attrib, value) construct_attributes[attrib] = value end
Apply the default and overrides attributes from the expansion passed in, which came from roles.
# File lib/chef/node.rb, line 450 def apply_expansion_attributes(expansion) load_chef_environment_object = (chef_environment == "_default" ? nil : Chef::Environment.load(chef_environment)) environment_default_attrs = load_chef_environment_object.nil? ? {} : load_chef_environment_object.default_attributes default_before_roles = Chef::Mixin::DeepMerge.merge(default_attrs, environment_default_attrs) @default_attrs = Chef::Mixin::DeepMerge.merge(default_before_roles, expansion.default_attrs) environment_override_attrs = load_chef_environment_object.nil? ? {} : load_chef_environment_object.override_attributes overrides_before_environments = Chef::Mixin::DeepMerge.merge(override_attrs, expansion.override_attrs) @override_attrs = Chef::Mixin::DeepMerge.merge(overrides_before_environments, environment_override_attrs) end
Used by the DSL
# File lib/chef/node.rb, line 237 def attribute construct_attributes end
# File lib/chef/node.rb, line 245 def attribute=(value) self.normal_attrs = value end
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 328 def attribute?(attrib) construct_attributes.attribute?(attrib) end
Remove this node from the CouchDB
# File lib/chef/node.rb, line 608 def cdb_destroy couchdb.delete("node", name, couchdb_rev) end
Save this node to the CouchDB
# File lib/chef/node.rb, line 618 def cdb_save @couchdb_rev = couchdb.store("node", name, self)["rev"] end
# File lib/chef/node.rb, line 228 def chef_environment(arg=nil) set_or_return( :chef_environment, arg, { :regex => /^[\-[:alnum:]_]+$/, :kind_of => String } ) end
# File lib/chef/node.rb, line 191 def chef_server_rest Chef::REST.new(Chef::Config[:chef_server_url]) end
# File lib/chef/node.rb, line 241 def construct_attributes Chef::Node::Attribute.new(normal_attrs, default_attrs, override_attrs, automatic_attrs) end
Consumes the combined run_list and other attributes in attrs
# File lib/chef/node.rb, line 391 def consume_attributes(attrs) normal_attrs_to_merge = consume_run_list(attrs) Chef::Log.debug("Applying attributes from json file") @normal_attrs = Chef::Mixin::DeepMerge.merge(@normal_attrs,normal_attrs_to_merge) self.tags # make sure they're defined end
Consume data from ohai and Attributes provided as JSON on the command line.
# File lib/chef/node.rb, line 378 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) @automatic_attrs = ohai_data platform, version = Chef::Platform.find_platform_and_version(self) Chef::Log.debug("Platform is #{platform} version #{version}") @automatic_attrs[:platform] = platform @automatic_attrs[:platform_version] = version end
Extracts the run list from attrs and applies it. Returns the remaining attributes
# File lib/chef/node.rb, line 405 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 JSON") run_list(new_run_list) end attrs end
# File lib/chef/node.rb, line 181 def couchdb_id=(value) @couchdb_id = value @index_id = value end
Create the node via the REST API
# File lib/chef/node.rb, line 640 def create chef_server_rest.post_rest("nodes", self) self end
Set a default of this node, but auto-vivifiy any Mashes that might be missing
# File lib/chef/node.rb, line 287 def default attrs = construct_attributes attrs.set_type = :default attrs.auto_vivifiy_on_read = true attrs end
Set a default attribute of this node, auto-vivifiying any mashes that are missing, but if the final value already exists, don't set it
# File lib/chef/node.rb, line 296 def default_unless attrs = construct_attributes attrs.set_type = :default attrs.auto_vivifiy_on_read = true attrs.set_unless_value_present = true attrs end
Remove this node via the REST API
# File lib/chef/node.rb, line 613 def destroy chef_server_rest.delete_rest("nodes/#{name}") end
# File lib/chef/node.rb, line 475 def display_hash display = {} display["name"] = name display["chef_environment"] = chef_environment display["automatic"] = automatic_attrs display["normal"] = normal_attrs display["default"] = default_attrs display["override"] = override_attrs display["run_list"] = run_list.run_list display end
Yield each key of the top level to the block.
# File lib/chef/node.rb, line 333 def each(&block) construct_attributes.each(&block) end
Iterates over each attribute, passing the attribute and value to the block.
# File lib/chef/node.rb, line 338 def each_attribute(&block) construct_attributes.each_attribute(&block) end
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 436 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 expansion end
Find a recipe for this Chef::Node by fqdn. Will search first for Chef::Config, then hostname.rb, then default.rb.
Returns a new Chef::Node object.
Raises an ArgumentError if it cannot find the node.
# File lib/chef/node.rb, line 201 def find_file(fqdn) host_parts = fqdn.split(".") hostname = host_parts[0] [fqdn, hostname, "default"].each { |fname| node_file = File.join(Chef::Config[:node_path], "#{fname.to_s}.rb") return self.from_file(node_file) if File.exists?(node_file) } raise ArgumentError, "Cannot find a node matching #{fqdn}, not even with default.rb!" end
Used by DSL. Loads the attribute file specified by the short name of the file, e.g., loads specified cookbook's
"attributes/mailservers.rb"
if passed
"mailservers"
# File lib/chef/node.rb, line 671 def load_attribute_by_short_filename(name, src_cookbook_name) src_cookbook = cookbook_collection[src_cookbook_name] raise Chef::Exceptions::CookbookNotFound, "could not find cookbook #{src_cookbook_name} while loading attribute #{name}" unless src_cookbook attribute_filename = src_cookbook.attribute_filenames_by_short_filename[name] raise Chef::Exceptions::AttributeNotFound, "could not find filename for attribute #{name} in cookbook #{src_cookbook_name}" unless attribute_filename self.from_file(attribute_filename) self end
Load all attribute files for all cookbooks associated with this node.
# File lib/chef/node.rb, line 656 def load_attributes cookbook_collection.values.each do |cookbook| cookbook.segment_filenames(:attributes).each do |segment_filename| Chef::Log.debug("Node #{name} loading cookbook #{cookbook.name}'s attribute file #{segment_filename}") self.from_file(segment_filename) end end end
Encouraged to only get used for lookups - while you can do sets from here, it's not as explicit as using the normal/default/override interface.
# File lib/chef/node.rb, line 344 def method_missing(symbol, *args) attrs = construct_attributes attrs.send(symbol, *args) end
Set the name of this Node, or return the current name.
# File lib/chef/node.rb, line 214 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
Set a normal attribute of this node, but auto-vivifiy any Mashes that might be missing
# File lib/chef/node.rb, line 265 def normal attrs = construct_attributes attrs.set_type = :normal attrs.auto_vivifiy_on_read = true attrs end
Set a normal attribute of this node, auto-vivifiying any mashes that are missing, but if the final value already exists, don't set it
# File lib/chef/node.rb, line 276 def normal_unless attrs = construct_attributes attrs.set_type = :normal attrs.auto_vivifiy_on_read = true attrs.set_unless_value_present = true attrs end
Set an override attribute of this node, but auto-vivifiy any Mashes that might be missing
# File lib/chef/node.rb, line 306 def override attrs = construct_attributes attrs.set_type = :override attrs.auto_vivifiy_on_read = true attrs end
Set an override attribute of this node, auto-vivifiying any mashes that are missing, but if the final value already exists, don't set it
# File lib/chef/node.rb, line 315 def override_unless attrs = construct_attributes attrs.set_type = :override attrs.auto_vivifiy_on_read = true attrs.set_unless_value_present = true attrs end
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 run_state, which is populated by include_recipe statements in the DSL (and thus would not be in the run list).
NOTE: It's used by cookbook authors
# File lib/chef/node.rb, line 357 def recipe?(recipe_name) run_list.include?(recipe_name) || run_state[:seen_recipes].include?(recipe_name) end
Clear defaults and overrides, so that any deleted attributes between runs are still gone.
# File lib/chef/node.rb, line 419 def reset_defaults_and_overrides @default_attrs = Mash.new @override_attrs = Mash.new end
Returns true if this Node expects a given role, false if not.
# File lib/chef/node.rb, line 362 def role?(role_name) run_list.include?("role[#{role_name}]") end
Returns true if this Node expects a given role, false if not.
# File lib/chef/node.rb, line 373 def run_list?(item) run_list.detect { |r| r == item } ? true : false end
Save this node via the REST API
# File lib/chef/node.rb, line 623 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}", self) end rescue Net::HTTPServerException => e raise e unless e.response.code == "404" chef_server_rest.post_rest("nodes", self) end self end
# File lib/chef/node.rb, line 259 def store(attrib, value) self[attrib] = value end
Transform the node to a Hash
# File lib/chef/node.rb, line 461 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
Serialize this object as a hash
# File lib/chef/node.rb, line 488 def to_json(*a) result = { "name" => name, "chef_environment" => chef_environment, 'json_class' => self.class.name, "automatic" => automatic_attrs, "normal" => normal_attrs, "chef_type" => "node", "default" => default_attrs, "override" => override_attrs, #Render correctly for run_list items so malformed json does not result "run_list" => run_list.run_list.map { |item| item.to_s } } result["_rev"] = couchdb_rev if couchdb_rev result.to_json(*a) end
# File lib/chef/node.rb, line 505 def update_from!(o) run_list.reset!(o.run_list) @automatic_attrs = o.automatic_attrs @normal_attrs = o.normal_attrs @override_attrs = o.override_attrs @default_attrs = o.default_attrs chef_environment(o.chef_environment) self end
Generated with the Darkfish Rdoc Generator 2.