Class: Chef::Node

Inherits:
Object show all
Extended by:
Forwardable
Includes:
IndexQueue::Indexable, Mixin::CheckHelper, Mixin::FromFile, Mixin::LanguageIncludeAttribute, Mixin::ParamsValidate
Defined in:
lib/chef/node.rb,
lib/chef/node/attribute.rb

Defined Under Namespace

Classes: Attribute

Constant Summary collapse

DESIGN_DOCUMENT =
{
  "version" => 11,
  "language" => "javascript",
  "views" => {
    "all" => {
      "map" => <<-EOJS
      function(doc) {
        if (doc.chef_type == "node") {
          emit(doc.name, doc);
        }
      }
      EOJS
    },
    "all_id" => {
      "map" => <<-EOJS
      function(doc) {
        if (doc.chef_type == "node") {
          emit(doc.name, doc.name);
        }
      }
      EOJS
    },
    "status" => {
      "map" => <<-EOJS
        function(doc) {
          if (doc.chef_type == "node") {
            var to_emit = { "name": doc.name, "chef_environment": doc.chef_environment };
            if (doc["attributes"]["fqdn"]) {
              to_emit["fqdn"] = doc["attributes"]["fqdn"];
            } else {
              to_emit["fqdn"] = "Undefined";
            }
            if (doc["attributes"]["ipaddress"]) {
              to_emit["ipaddress"] = doc["attributes"]["ipaddress"];
            } else {
              to_emit["ipaddress"] = "Undefined";
            }
            if (doc["attributes"]["ohai_time"]) {
              to_emit["ohai_time"] = doc["attributes"]["ohai_time"];
            } else {
              to_emit["ohai_time"] = "Undefined";
            }
            if (doc["attributes"]["uptime"]) {
              to_emit["uptime"] = doc["attributes"]["uptime"];
            } else {
              to_emit["uptime"] = "Undefined";
            }
            if (doc["attributes"]["platform"]) {
              to_emit["platform"] = doc["attributes"]["platform"];
            } else {
              to_emit["platform"] = "Undefined";
            }
            if (doc["attributes"]["platform_version"]) {
              to_emit["platform_version"] = doc["attributes"]["platform_version"];
            } else {
              to_emit["platform_version"] = "Undefined";
            }
            if (doc["run_list"]) {
              to_emit["run_list"] = doc["run_list"];
            } else {
              to_emit["run_list"] = "Undefined";
            }
            emit(doc.name, to_emit);
          }
        }
      EOJS
    },
    "by_run_list" => {
      "map" => <<-EOJS
        function(doc) {
          if (doc.chef_type == "node") {
            if (doc['run_list']) {
              for (var i=0; i < doc.run_list.length; i++) {
                emit(doc['run_list'][i], doc.name);
              }
            }
          }
        }
      EOJS
    },
    "by_environment" => {
      "map" => <<-EOJS
        function(doc) {
          if (doc.chef_type == "node") {
            var env = (doc['chef_environment'] == null ? "_default" : doc['chef_environment']);
            emit(env, doc.name);
          }
        }
      EOJS
    }
  },
}

Instance Attribute Summary collapse

Attributes included from IndexQueue::Indexable

#index_id

Class Method Summary collapse

Instance Method Summary collapse

Methods included from IndexQueue::Indexable

#add_to_index, #delete_from_index, included, #index_object_type, #with_indexer_metadata

Methods included from Mixin::LanguageIncludeAttribute

#include_attribute

Methods included from Mixin::ParamsValidate

#set_or_return, #validate

Methods included from Mixin::FromFile

#class_from_file, #from_file

Methods included from Mixin::CheckHelper

#set_if_args

Constructor Details

#initialize(couchdb = nil) ⇒ Node

Create a new Chef::Node object.


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object

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.


344
345
346
347
# File 'lib/chef/node.rb', line 344

def method_missing(symbol, *args)
  attrs = construct_attributes
  attrs.send(symbol, *args)
end

Instance Attribute Details

#automatic_attrsObject

Returns the value of attribute automatic_attrs


49
50
51
# File 'lib/chef/node.rb', line 49

def automatic_attrs
  @automatic_attrs
end

#cookbook_collectionObject

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


55
56
57
# File 'lib/chef/node.rb', line 55

def cookbook_collection
  @cookbook_collection
end

#couchdbObject

Returns the value of attribute couchdb


48
49
50
# File 'lib/chef/node.rb', line 48

def couchdb
  @couchdb
end

#couchdb_idObject

Returns the value of attribute couchdb_id


50
51
52
# File 'lib/chef/node.rb', line 50

def couchdb_id
  @couchdb_id
end

#couchdb_revObject

Returns the value of attribute couchdb_rev


48
49
50
# File 'lib/chef/node.rb', line 48

def couchdb_rev
  @couchdb_rev
end

#default_attrsObject

Returns the value of attribute default_attrs


49
50
51
# File 'lib/chef/node.rb', line 49

def default_attrs
  @default_attrs
end

#normal_attrsObject

Returns the value of attribute normal_attrs


49
50
51
# File 'lib/chef/node.rb', line 49

def normal_attrs
  @normal_attrs
end

#override_attrsObject

Returns the value of attribute override_attrs


49
50
51
# File 'lib/chef/node.rb', line 49

def override_attrs
  @override_attrs
end

#recipe_listObject

Returns the value of attribute recipe_list


48
49
50
# File 'lib/chef/node.rb', line 48

def recipe_list
  @recipe_list
end

#run_list(*args) ⇒ Object

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.


368
369
370
# File 'lib/chef/node.rb', line 368

def run_list
  @run_list
end

#run_stateObject

Returns the value of attribute run_state


48
49
50
# File 'lib/chef/node.rb', line 48

def run_state
  @run_state
end

Class Method Details

.build(node_name) ⇒ Object


594
595
596
597
598
599
# File 'lib/chef/node.rb', line 594

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

.cdb_list(inflate = false, couchdb = nil) ⇒ Object

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.


555
556
557
558
559
# File 'lib/chef/node.rb', line 555

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

.cdb_list_by_environment(environment, inflate = false, couchdb = nil) ⇒ Object


538
539
540
541
# File 'lib/chef/node.rb', line 538

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

.cdb_load(name, couchdb = nil) ⇒ Object

Load a node by name from CouchDB


574
575
576
# File 'lib/chef/node.rb', line 574

def self.cdb_load(name, couchdb=nil)
  (couchdb || Chef::CouchDB.new).load("node", name)
end

.create_design_document(couchdb = nil) ⇒ Object

Set up our CouchDB design document


641
642
643
# File 'lib/chef/node.rb', line 641

def self.create_design_document(couchdb=nil)
  (couchdb || Chef::CouchDB.new).create_design_document("nodes", DESIGN_DOCUMENT)
end

.exists?(nodename, couchdb) ⇒ Boolean


578
579
580
581
582
583
584
# File 'lib/chef/node.rb', line 578

def self.exists?(nodename, couchdb)
  begin
    self.cdb_load(nodename, couchdb)
  rescue Chef::Exceptions::CouchDBNotFound
    nil
  end
end

.find_or_create(node_name) ⇒ Object


586
587
588
589
590
591
592
# File 'lib/chef/node.rb', line 586

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) ⇒ Object

Create a Chef::Node from JSON


515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
# File 'lib/chef/node.rb', line 515

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

.list(inflate = false) ⇒ Object


561
562
563
564
565
566
567
568
569
570
571
# File 'lib/chef/node.rb', line 561

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) ⇒ Object


543
544
545
546
547
548
549
550
551
# File 'lib/chef/node.rb', line 543

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) ⇒ Object

Load a node by name


602
603
604
# File 'lib/chef/node.rb', line 602

def self.load(name)
  Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("nodes/#{name}")
end

Instance Method Details

#[](attrib) ⇒ Object

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


250
251
252
# File 'lib/chef/node.rb', line 250

def [](attrib)
  construct_attributes[attrib]
end

#[]=(attrib, value) ⇒ Object

Set an attribute of this node


255
256
257
# File 'lib/chef/node.rb', line 255

def []=(attrib, value)
  construct_attributes[attrib] = value
end

#apply_expansion_attributes(expansion) ⇒ Object

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


450
451
452
453
454
455
456
457
458
# 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

#attributeObject

Used by the DSL


237
238
239
# File 'lib/chef/node.rb', line 237

def attribute
  construct_attributes
end

#attribute=(value) ⇒ Object


245
246
247
# File 'lib/chef/node.rb', line 245

def attribute=(value)
  self.normal_attrs = value
end

#attribute?(attrib) ⇒ Boolean

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?()


328
329
330
# File 'lib/chef/node.rb', line 328

def attribute?(attrib)
  construct_attributes.attribute?(attrib)
end

#cdb_destroyObject

Remove this node from the CouchDB


607
608
609
# File 'lib/chef/node.rb', line 607

def cdb_destroy
  couchdb.delete("node", name, couchdb_rev)
end

#cdb_saveObject

Save this node to the CouchDB


617
618
619
# File 'lib/chef/node.rb', line 617

def cdb_save
  @couchdb_rev = couchdb.store("node", name, self)["rev"]
end

#chef_environment(arg = nil) ⇒ Object


228
229
230
231
232
233
234
# File 'lib/chef/node.rb', line 228

def chef_environment(arg=nil)
  set_or_return(
    :chef_environment,
    arg,
    { :regex => /^[\-[:alnum:]_]+$/, :kind_of => String }
  )
end

#chef_server_restObject


191
192
193
# File 'lib/chef/node.rb', line 191

def chef_server_rest
  Chef::REST.new(Chef::Config[:chef_server_url])
end

#construct_attributesObject


241
242
243
# File 'lib/chef/node.rb', line 241

def construct_attributes
  Chef::Node::Attribute.new(normal_attrs, default_attrs, override_attrs, automatic_attrs)
end

#consume_attributes(attrs) ⇒ Object

Consumes the combined run_list and other attributes in attrs


391
392
393
394
395
396
# 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_external_attrs(ohai_data, json_cli_attrs) ⇒ Object

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


378
379
380
381
382
383
384
385
386
387
388
# 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

#consume_run_list(attrs) ⇒ Object

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


405
406
407
408
409
410
411
412
413
414
415
# 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

#createObject

Create the node via the REST API


635
636
637
638
# File 'lib/chef/node.rb', line 635

def create
  chef_server_rest.post_rest("nodes", self)
  self
end

#defaultObject

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


287
288
289
290
291
292
# File 'lib/chef/node.rb', line 287

def default
  attrs = construct_attributes
  attrs.set_type = :default
  attrs.auto_vivifiy_on_read = true
  attrs
end

#default_unlessObject

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


296
297
298
299
300
301
302
# 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

#destroyObject

Remove this node via the REST API


612
613
614
# File 'lib/chef/node.rb', line 612

def destroy
  chef_server_rest.delete_rest("nodes/#{name}")
end

#display_hashObject


475
476
477
478
479
480
481
482
483
484
485
# 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

#each(&block) ⇒ Object

Yield each key of the top level to the block.


333
334
335
# File 'lib/chef/node.rb', line 333

def each(&block)
  construct_attributes.each(&block)
end

#each_attribute(&block) ⇒ Object

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


338
339
340
# File 'lib/chef/node.rb', line 338

def each_attribute(&block)
  construct_attributes.each_attribute(&block)
end

#expand!(data_source = 'server') ⇒ Object

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.

– TODO: timh/cw, 5-14-2010: Should this method exist? Should we instead modify default_attrs and override_attrs whenever our run_list is mutated? Or perhaps do something smarter like on-demand generation of default_attrs and override_attrs, invalidated only when run_list is mutated?


436
437
438
439
440
441
442
443
444
445
446
# File 'lib/chef/node.rb', line 436

def expand!(data_source = 'server')
  expansion = run_list.expand(chef_environment, data_source)
  raise Chef::Exceptions::MissingRole if expansion.errors?

  self.tags # make sure they're defined

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

  expansion
end

#find_file(fqdn) ⇒ Object

Find a recipe for this Chef::Node by fqdn. Will search first for Chef::Config/fqdn.rb, then hostname.rb, then default.rb.

Returns a new Chef::Node object.

Raises an ArgumentError if it cannot find the node.

Raises:

  • (ArgumentError)

201
202
203
204
205
206
207
208
209
210
211
# 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

#load_attribute_by_short_filename(name, src_cookbook_name) ⇒ Object

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"

666
667
668
669
670
671
672
673
674
675
# File 'lib/chef/node.rb', line 666

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_attributesObject

Load all attribute files for all cookbooks associated with this node.


651
652
653
654
655
656
657
658
# File 'lib/chef/node.rb', line 651

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

#name(arg = nil) ⇒ Object

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


214
215
216
217
218
219
220
221
222
223
224
225
226
# 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

#nodeObject

Used by DSL


187
188
189
# File 'lib/chef/node.rb', line 187

def node
  self
end

#normalObject Also known as: set

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


265
266
267
268
269
270
# File 'lib/chef/node.rb', line 265

def normal
  attrs = construct_attributes
  attrs.set_type = :normal
  attrs.auto_vivifiy_on_read = true
  attrs
end

#normal_unlessObject Also known as: set_unless

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


276
277
278
279
280
281
282
# 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

#overrideObject

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


306
307
308
309
310
311
# File 'lib/chef/node.rb', line 306

def override
  attrs = construct_attributes
  attrs.set_type = :override
  attrs.auto_vivifiy_on_read = true
  attrs
end

#override_unlessObject

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


315
316
317
318
319
320
321
# 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

#recipe?(recipe_name) ⇒ Boolean

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


357
358
359
# File 'lib/chef/node.rb', line 357

def recipe?(recipe_name)
  run_list.include?(recipe_name) || run_state[:seen_recipes].include?(recipe_name)
end

#reset_defaults_and_overridesObject

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


419
420
421
422
# File 'lib/chef/node.rb', line 419

def reset_defaults_and_overrides
  @default_attrs = Mash.new
  @override_attrs = Mash.new
end

#role?(role_name) ⇒ Boolean

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


362
363
364
# File 'lib/chef/node.rb', line 362

def role?(role_name)
  run_list.include?("role[#{role_name}]")
end

#run_list?(item) ⇒ Boolean

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


373
374
375
# File 'lib/chef/node.rb', line 373

def run_list?(item)
  run_list.detect { |r| r == item } ? true : false
end

#saveObject

Save this node via the REST API


622
623
624
625
626
627
628
629
630
631
632
# File 'lib/chef/node.rb', line 622

def save
  # Try PUT. If the node doesn't yet exist, PUT will return 404,
  # so then POST to create.
  begin
    chef_server_rest.put_rest("nodes/#{name}", self)
  rescue Net::HTTPServerException => e
    raise e unless e.response.code == "404"
    chef_server_rest.post_rest("nodes", self)
  end
  self
end

#store(attrib, value) ⇒ Object


259
260
261
# File 'lib/chef/node.rb', line 259

def store(attrib, value)
  self[attrib] = value
end

#tagsObject

Lazy initializer for tags attribute


399
400
401
402
# File 'lib/chef/node.rb', line 399

def tags
  self[:tags] = [] unless attribute?(:tags)
  self[:tags]
end

#to_hashObject

Transform the node to a Hash


461
462
463
464
465
466
467
468
469
470
471
472
473
# 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

#to_json(*a) ⇒ Object

Serialize this object as a hash


488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# 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,
    "run_list" => run_list.run_list
  }
  result["_rev"] = couchdb_rev if couchdb_rev
  result.to_json(*a)
end

#to_sObject


645
646
647
# File 'lib/chef/node.rb', line 645

def to_s
  "node[#{name}]"
end

#update_from!(o) ⇒ Object


504
505
506
507
508
509
510
511
512
# File 'lib/chef/node.rb', line 504

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