Class: ChefAPI::Resource::Base

Inherits:
Object
  • Object
show all
Extended by:
Enumerable
Defined in:
lib/chef-api/resources/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, prefix = {}) {|_self| ... } ⇒ Base

Initialize a new resource with the given attributes. These attributes are merged with the default values from the schema. Any attributes that aren’t defined in the schema are silently ignored for security purposes.

Examples:

create a resource using attributes

Bacon.new(foo: 'bar', zip: 'zap') #=> #<ChefAPI::Resource::Bacon>

using a block

Bacon.new do |bacon|
  bacon.foo = 'bar'
  bacon.zip = 'zap'
end

Parameters:

  • attributes (Hash) (defaults to: {})

    the list of initial attributes to set on the model

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Yields:

  • (_self)

Yield Parameters:



558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
# File 'lib/chef-api/resources/base.rb', line 558

def initialize(attributes = {}, prefix = {})
  @schema = self.class.schema.dup
  @schema.load_flavor(self.class.connection.flavor)

  @associations = {}
  @_prefix      = prefix

  # Define a getter and setter method for each attribute in the schema
  _attributes.each do |key, value|
    define_singleton_method(key) { _attributes[key] }
    define_singleton_method("#{key}=") { |value| update_attribute(key, value) }
  end

  attributes.each do |key, value|
    unless ignore_attribute?(key)
      update_attribute(key, value)
    end
  end

  yield self if block_given?
end

Instance Attribute Details

#associationsHash (readonly)

The list of associations.

Returns:

  • (Hash)


536
537
538
# File 'lib/chef-api/resources/base.rb', line 536

def associations
  @associations
end

Class Method Details

.allArray<Resource::Base>

Note:

Unless you need the entire collection, please consider using the

Return an array of all resources in the collection.

size and each methods instead as they are much more perforant.

Returns:



393
394
395
# File 'lib/chef-api/resources/base.rb', line 393

def all
  entries
end

.build(attributes = {}, prefix = {}) ⇒ Object

Build a new resource from the given attributes.

Examples:

build an empty resource

Bacon.build #=> #<ChefAPI::Resource::Bacon>

build a resource with attributes

Bacon.build(foo: 'bar') #=> #<ChefAPI::Resource::Baocn foo: bar>

Parameters:

  • attributes (Hash) (defaults to: {})

    the list of attributes for the new resource - any attributes that are not defined in the schema are silently ignored

See Also:



275
276
277
# File 'lib/chef-api/resources/base.rb', line 275

def build(attributes = {}, prefix = {})
  new(attributes, prefix)
end

.classnameString

The name for this resource, minus the parent module.

Examples:

classname #=> Resource::Bacon

Returns:

  • (String)


448
449
450
# File 'lib/chef-api/resources/base.rb', line 448

def classname
  name.split("::")[1..-1].join("::")
end

.collection(prefix = {}) ⇒ Array<Resource::Base>

The full collection list.

Parameters:

  • prefix (Hash) (defaults to: {})

    any prefix options to use

Returns:



473
474
475
# File 'lib/chef-api/resources/base.rb', line 473

def collection(prefix = {})
  connection.get(expanded_collection_path(prefix))
end

.collection_path(value = UNSET) ⇒ Symbol, String

Get or set the name of the remote resource collection. This is most likely the remote API endpoint (such as /clients), without the leading slash.

Examples:

Setting a base collection path

collection_path '/clients'

Setting a collection path with nesting

collection_path '/data/:name'

Parameters:

  • value (Symbol) (defaults to: UNSET)

    the value to use for the collection name.

Returns:

  • (Symbol, String)

    the name of the collection



118
119
120
121
122
123
124
125
# File 'lib/chef-api/resources/base.rb', line 118

def collection_path(value = UNSET)
  if value != UNSET
    @collection_path = value.to_s
  else
    @collection_path ||
      raise(ArgumentError, "collection_path not set for #{self.class}")
  end
end

.connectionChefAPI::Connection

The current connection object.

Returns:



526
527
528
# File 'lib/chef-api/resources/base.rb', line 526

def connection
  Thread.current["chefapi.connection"] || ChefAPI.connection
end

.count(prefix = {}) ⇒ Fixnum Also known as: size

The total number of reosurces in the collection.

Returns:

  • (Fixnum)


380
381
382
# File 'lib/chef-api/resources/base.rb', line 380

def count(prefix = {})
  collection(prefix).size
end

.create(attributes = {}, prefix = {}) ⇒ Resource::Base

Create a new resource and save it to the Chef Server, raising any exceptions that might occur. This method will save the resource back to the Chef Server, raising any validation errors that occur.

Parameters:

  • attributes (Hash) (defaults to: {})

    the list of attributes to set on the new resource

Returns:

Raises:



295
296
297
298
299
300
301
302
303
304
# File 'lib/chef-api/resources/base.rb', line 295

def create(attributes = {}, prefix = {})
  resource = build(attributes, prefix)

  unless resource.new_resource?
    raise Error::ResourceAlreadyExists.new
  end

  resource.save!
  resource
end

.delete(id, prefix = {}) ⇒ true

Delete the remote resource from the Chef Sserver.

Parameters:

  • id (String, Fixnum)

    the id of the resource to delete

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (true)


176
177
178
179
180
181
182
# File 'lib/chef-api/resources/base.rb', line 176

def delete(id, prefix = {})
  path = resource_path(id, prefix)
  connection.delete(path)
  true
rescue Error::HTTPNotFound
  true
end

.destroy(id, prefix = {}) ⇒ Base?

Destroy a record with the given id.

Parameters:

  • id (String, Fixnum)

    the id of the resource to delete

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (Base, nil)

    the destroyed resource, or nil if the resource does not exist on the remote Chef Server



215
216
217
218
219
220
221
# File 'lib/chef-api/resources/base.rb', line 215

def destroy(id, prefix = {})
  resource = fetch(id, prefix)
  return nil if resource.nil?

  resource.destroy
  resource
end

.destroy_all(prefix = {}) ⇒ Array<Base>

Delete all remote resources of the given type from the Chef Server

Parameters:

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (Array<Base>)

    an array containing the list of resources that were deleted



231
232
233
# File 'lib/chef-api/resources/base.rb', line 231

def destroy_all(prefix = {})
  map(&:destroy)
end

.each(prefix = {}, &block) ⇒ Object

(Lazy) iterate over each item in the collection, yielding the fully- built resource object. This method, coupled with the Enumerable module, provides us with other methods like first and map.

Examples:

get the first resource

Bacon.first #=> #<ChefAPI::Resource::Bacon>

get the first 3 resources

Bacon.first(3) #=> [#<ChefAPI::Resource::Bacon>, ...]

iterate over each resource

Bacon.each { |bacon| puts bacon.name }

get all the resource’s names

Bacon.map(&:name) #=> ["ham", "sausage", "turkey"]


366
367
368
369
370
371
372
373
# File 'lib/chef-api/resources/base.rb', line 366

def each(prefix = {}, &block)
  collection(prefix).each do |resource, path|
    response = connection.get(path)
    result = from_json(response, prefix)

    block.call(result) if block
  end
end

.exists?(id, prefix = {}) ⇒ Boolean

Check if the given resource exists on the Chef Server.

Parameters:

  • id (String, Fixnum)

    the id of the resource to fetch

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:



316
317
318
# File 'lib/chef-api/resources/base.rb', line 316

def exists?(id, prefix = {})
  !fetch(id, prefix).nil?
end

.expanded_collection_path(prefix = {}) ⇒ String

Expand the collection path, “interpolating” any parameters. This syntax is heavily borrowed from Rails and it will make more sense by looking at an example.

Examples:

/bacon, {} #=> "foo"
/bacon/:type, { type: 'crispy' } #=> "bacon/crispy"

Parameters:

  • prefix (Hash) (defaults to: {})

    the list of prefix options

Returns:

  • (String)

    the “interpolated” URL string

Raises:



508
509
510
511
512
513
514
515
516
517
518
519
# File 'lib/chef-api/resources/base.rb', line 508

def expanded_collection_path(prefix = {})
  collection_path.gsub(/:\w+/) do |param|
    key = param.delete(":")
    value = prefix[key] || prefix[key.to_sym]

    if value.nil?
      raise Error::MissingURLParameter.new(param: key)
    end

    CGI.escape(value)
  end.sub(%r{^/}, "") # Remove leading slash
end

.fetch(id, prefix = {}) ⇒ Resource::Base?

Fetch a single resource in the remote collection.

Examples:

fetch a single client

Client.fetch('chef-webui') #=> #<Client name: 'chef-webui', ...>

Parameters:

  • id (String, Fixnum)

    the id of the resource to fetch

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (Resource::Base, nil)

    an instance of the resource, or nil if that given resource does not exist



250
251
252
253
254
255
256
257
258
# File 'lib/chef-api/resources/base.rb', line 250

def fetch(id, prefix = {})
  return nil if id.nil?

  path     = resource_path(id, prefix)
  response = connection.get(path)
  from_json(response, prefix)
rescue Error::HTTPNotFound
  nil
end

.from_file(path) ⇒ Object

Load the given resource from it’s on-disk equivalent. This action only makes sense for some resources, and must be defined on a per-resource basis, since the logic varies between resources.

Parameters:

  • path (String)

    the path to the file on disk

Raises:



17
18
19
# File 'lib/chef-api/resources/base.rb', line 17

def from_file(path)
  raise Error::AbstractMethod.new(method: "Resource::Base#from_file")
end

.from_json(response, prefix = {}) ⇒ Resource::Base

Construct the object from a JSON response. This method actually just delegates to the new method, but it removes some marshall data and whatnot from the response first.

Parameters:

  • response (String)

    the JSON response from the Chef Server

Returns:

  • (Resource::Base)

    an instance of the resource represented by this JSON



408
409
410
411
412
413
# File 'lib/chef-api/resources/base.rb', line 408

def from_json(response, prefix = {})
  response.delete("json_class")
  response.delete("chef_type")

  new(response, prefix)
end

.from_url(url, prefix = {}) ⇒ Object

TODO:

doc



24
25
26
# File 'lib/chef-api/resources/base.rb', line 24

def from_url(url, prefix = {})
  from_json(connection.get(url), prefix)
end

.has_many(method, options = {}) ⇒ Object

Create a nested relationship collection. The associated collection is cached on the class, reducing API requests.

Examples:

Create an association to environments


has_many :environments

Create an association with custom configuration


has_many :environments, class_name: 'Environment'


82
83
84
85
86
87
88
89
90
91
92
# File 'lib/chef-api/resources/base.rb', line 82

def has_many(method, options = {})
  class_name    = options[:class_name] || "Resource::#{Util.camelize(method).sub(/s$/, "")}"
  rest_endpoint = options[:rest_endpoint] || method

  class_eval <<-EOH, __FILE__, __LINE__ + 1
    def #{method}
      associations[:#{method}] ||=
        Resource::CollectionProxy.new(self, #{class_name}, '#{rest_endpoint}')
    end
  EOH
end

.inspectString

The detailed string representation of this class, including the full schema definition.

Examples:

for the Bacon class

Bacon.inspect #=> "Resource::Bacon(id, description, ...)"

Returns:

  • (String)


436
437
438
# File 'lib/chef-api/resources/base.rb', line 436

def inspect
  "#{classname}(#{schema.attributes.keys.join(", ")})"
end

.list(prefix = {}) ⇒ Array<String>

Get the “list” of items in this resource. This list contains the primary keys of all of the resources in this collection. This method is useful in CLI applications, because it only makes a single API request to gather this data.

Examples:

Get the list of all clients

Client.list #=> ['validator', 'chef-webui']

Parameters:

  • prefix (Hash) (defaults to: {})

    the listof prefix options (for nested resources)

Returns:

  • (Array<String>)


198
199
200
201
# File 'lib/chef-api/resources/base.rb', line 198

def list(prefix = {})
  path = expanded_collection_path(prefix)
  connection.get(path).keys.sort
end

.post(body, prefix = {}) ⇒ String

Make an authenticated HTTP POST request using the connection object. This method returns a new object representing the response from the server, which should be merged with an existing object’s attributes to reflect the newest state of the resource.

Parameters:

  • body (Hash)

    the request body to create the resource with (probably JSON)

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (String)

    the JSON response from the server



141
142
143
144
# File 'lib/chef-api/resources/base.rb', line 141

def post(body, prefix = {})
  path = expanded_collection_path(prefix)
  connection.post(path, body)
end

.protect(*ids) ⇒ Object

Protect one or more resources from being altered by the user. This is useful if there’s an admin client or magical cookbook that you don’t want users to modify.

Examples:

protect 'chef-webui', 'my-magical-validator'
protect ->(resource) { resource.name =~ /internal_(.+)/ }

Parameters:

  • ids (Array<String, Proc>)

    the list of “things” to protect



66
67
68
# File 'lib/chef-api/resources/base.rb', line 66

def protect(*ids)
  ids.each { |id| protected_resources << id }
end

.protected_resourcesObject

TODO:

doc



97
98
99
# File 'lib/chef-api/resources/base.rb', line 97

def protected_resources
  @protected_resources ||= []
end

.put(id, body, prefix = {}) ⇒ String

Perform a PUT request to the Chef Server against the given resource or resource identifier. The resource will be partially updated (this method doubles as PATCH) with the given parameters.

Parameters:

  • id (String, Resource::Base)

    a resource object or a string representing the unique identifier of the resource object to update

  • body (Hash)

    the request body to create the resource with (probably JSON)

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

  • (String)

    the JSON response from the server



162
163
164
165
# File 'lib/chef-api/resources/base.rb', line 162

def put(id, body, prefix = {})
  path = resource_path(id, prefix)
  connection.put(path, body)
end

.resource_path(id, prefix = {}) ⇒ String

The path to an individual resource.

Parameters:

  • prefix (Hash) (defaults to: {})

    the list of prefix options

Returns:

  • (String)

    the path to the resource



486
487
488
# File 'lib/chef-api/resources/base.rb', line 486

def resource_path(id, prefix = {})
  [expanded_collection_path(prefix), id].join("/")
end

.schema(&block) ⇒ Schema

Get or set the schema for the remote resource. You probably only want to call schema once with a block, because it will overwrite the existing schema (meaning entries are not merged). If a block is given, a new schema object is created, otherwise the current one is returned.

Examples:

schema do
  attribute :id, primary: true
  attribute :name, type: String, default: 'bacon'
  attribute :admin, type: Boolean, required: true
end

Returns:

  • (Schema)

    the schema object for this resource



44
45
46
47
48
49
50
# File 'lib/chef-api/resources/base.rb', line 44

def schema(&block)
  if block
    @schema = Schema.new(&block)
  else
    @schema
  end
end

.to_sString

The string representation of this class.

Examples:

for the Bacon class

Bacon.to_s #=> "Resource::Bacon"

Returns:

  • (String)


423
424
425
# File 'lib/chef-api/resources/base.rb', line 423

def to_s
  classname
end

.typeString

The type of this resource.

Examples:

bacon

Returns:

  • (String)


460
461
462
# File 'lib/chef-api/resources/base.rb', line 460

def type
  Util.underscore(name.split("::").last).gsub("_", " ")
end

.update(id, attributes = {}, prefix = {}) ⇒ Resource::Base

Perform a PUT request to the Chef Server for the current resource, updating the given parameters. The parameters may be a full or partial resource update, as supported by the Chef Server.

Parameters:

  • id (String, Fixnum)

    the id of the resource to update

  • attributes (Hash) (defaults to: {})

    the list of attributes to set on the new resource

  • prefix (Hash) (defaults to: {})

    the list of prefix options (for nested resources)

Returns:

Raises:



338
339
340
341
342
343
344
345
346
347
# File 'lib/chef-api/resources/base.rb', line 338

def update(id, attributes = {}, prefix = {})
  resource = fetch(id, prefix)

  unless resource
    raise Error::ResourceNotFound.new(type: type, id: id)
  end

  resource.update(attributes).save
  resource
end

Instance Method Details

#_attributesHash<Symbol, Object>

The list of attributes on this resource.

Returns:

  • (Hash<Symbol, Object>)


611
612
613
# File 'lib/chef-api/resources/base.rb', line 611

def _attributes
  @_attributes ||= {}.merge(@schema.attributes)
end

#_prefixObject

TODO:

doc



602
603
604
# File 'lib/chef-api/resources/base.rb', line 602

def _prefix
  @_prefix
end

#attribute?(key) ⇒ Boolean

Determine if this resource has the given attribute.

Parameters:

  • key (Symbol, String)

    the attribute key to find

Returns:

  • (Boolean)

    true if the attribute exists, false otherwise



624
625
626
# File 'lib/chef-api/resources/base.rb', line 624

def attribute?(key)
  _attributes.key?(key.to_sym)
end

#destroyself

Remove the resource from the Chef Server.

Returns:

  • (self)

    the current instance of this object



720
721
722
723
# File 'lib/chef-api/resources/base.rb', line 720

def destroy
  self.class.delete(id, _prefix)
  self
end

#diffHash

Note:

This is a VERY expensive operation - use it sparringly!

Calculate a differential of the attributes on the local resource with it’s remote Chef Server counterpart.

Examples:

when the local resource is in sync with the remote resource

bacon = Bacon.first
bacon.diff #=> {}

when the local resource differs from the remote resource

bacon = Bacon.first
bacon.description = "My new description"
bacon.diff #=> { :description => { :local => "My new description", :remote => "Old description" } }

Returns:

  • (Hash)


864
865
866
867
868
869
870
871
872
873
874
875
# File 'lib/chef-api/resources/base.rb', line 864

def diff
  diff = {}

  remote = self.class.fetch(id, _prefix) || self.class.new({}, _prefix)
  remote._attributes.each do |key, value|
    unless _attributes[key] == value
      diff[key] = { local: _attributes[key], remote: value }
    end
  end

  diff
end

#dirty?Boolean

Check if the local resource is in sync with the remote Chef Server. When a remote resource is updated, ChefAPI has no way of knowing it’s cached resources are dirty unless additional requests are made against the remote Chef Server and diffs are compared.

Examples:

when the resource is out of sync with the remote Chef Server

bacon = Bacon.first
bacon.description = "I'm different, yeah, I'm different!"
bacon.dirty? #=> true

when the resource is in sync with the remote Chef Server

bacon = Bacon.first
bacon.dirty? #=> false

Returns:

  • (Boolean)

    true if the local resource has differing attributes from the same resource on the remote Chef Server, false otherwise



843
844
845
# File 'lib/chef-api/resources/base.rb', line 843

def dirty?
  new_resource? || !diff.empty?
end

#errorsErrorCollection

The collection of errors on the resource.

Returns:



909
910
911
# File 'lib/chef-api/resources/base.rb', line 909

def errors
  @errors ||= ErrorCollection.new
end

#idObject

The unique id for this resource.

Returns:

  • (Object)


595
596
597
# File 'lib/chef-api/resources/base.rb', line 595

def id
  _attributes[primary_key]
end

#ignore_attribute?(key) ⇒ Boolean

Determine if a given attribute should be ignored. Ignored attributes are defined at the schema level and are frozen.

Parameters:

  • key (Symbol)

    the attribute to check ignorance

Returns:



900
901
902
# File 'lib/chef-api/resources/base.rb', line 900

def ignore_attribute?(key)
  @schema.ignored_attributes.key?(key.to_sym)
end

#inspectString

Custom inspect method for easier readability.

Returns:

  • (String)


950
951
952
953
954
955
956
957
958
959
960
# File 'lib/chef-api/resources/base.rb', line 950

def inspect
  attrs = (_prefix).merge(_attributes).map do |key, value|
    if value.is_a?(String)
      "#{key}: #{Util.truncate(value, length: 50).inspect}"
    else
      "#{key}: #{value.inspect}"
    end
  end

  "#<#{self.class.classname} #{attrs.join(", ")}>"
end

#new_resource?Boolean

Check if this resource exists on the remote Chef Server. This is useful when determining if a resource should be saved or updated, since a resource must exist before it can be saved.

Examples:

when the resource does not exist on the remote Chef Server

bacon = Bacon.new
bacon.new_resource? #=> true

when the resource exists on the remote Chef Server

bacon = Bacon.first
bacon.new_resource? #=> false

Returns:

  • (Boolean)

    true if the resource exists on the remote Chef Server, false otherwise



820
821
822
# File 'lib/chef-api/resources/base.rb', line 820

def new_resource?
  !self.class.exists?(id, _prefix)
end

#primary_keySymbol

The primary key for the resource.

Returns:

  • (Symbol)

    the primary key for this resource



586
587
588
# File 'lib/chef-api/resources/base.rb', line 586

def primary_key
  @schema.primary_key
end

#protected?Boolean

Determine if this current resource is protected. Resources may be protected by name or by a Proc. A protected resource is one that should not be modified (i.e. created/updated/deleted) by the user. An example of a protected resource is the pivotal key or the chef-webui client.

Returns:



636
637
638
639
640
641
642
643
644
# File 'lib/chef-api/resources/base.rb', line 636

def protected?
  @protected ||= self.class.protected_resources.any? do |thing|
    if thing.is_a?(Proc)
      thing.call(self)
    else
      id == thing
    end
  end
end

#reload!self

Note:

This will remove any custom values you have set on the resource!

Reload (or reset) this object using the values currently stored on the remote server. This method will also clear any cached collection proxies so they will be reloaded the next time they are requested. If the remote record does not exist, no attributes are modified.

Returns:

  • (self)

    the instance of the reloaded record



657
658
659
660
661
662
663
664
665
666
667
668
# File 'lib/chef-api/resources/base.rb', line 657

def reload!
  associations.clear

  remote = self.class.fetch(id, _prefix)
  return self if remote.nil?

  remote._attributes.each do |key, value|
    update_attribute(key, value)
  end

  self
end

#resource_pathString

The URL for this resource on the Chef Server.

Examples:

Get the resource path for a resource

bacon = Bacon.first
bacon.resource_path #=> /bacons/crispy

Returns:

  • (String)

    the partial URL path segment



887
888
889
# File 'lib/chef-api/resources/base.rb', line 887

def resource_path
  self.class.resource_path(id, _prefix)
end

#saveBoolean

Commit the resource and any changes to the remote Chef Server. Any errors are gracefully handled and added to the resource’s error collection for handling.

Returns:

  • (Boolean)

    true if the save was successfuly, false otherwise



708
709
710
711
712
# File 'lib/chef-api/resources/base.rb', line 708

def save
  save!
rescue
  false
end

#save!Boolean

Commit the resource and any changes to the remote Chef Server. Any errors will raise an exception in the main thread and the resource will not be committed back to the Chef Server.

Any response errors (such as server-side responses) that ChefAPI failed to account for in validations will also raise an exception.

Returns:

  • (Boolean)

    true if the resource was saved



681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
# File 'lib/chef-api/resources/base.rb', line 681

def save!
  validate!

  response = if new_resource?
               self.class.post(to_json, _prefix)
             else
               self.class.put(id, to_json, _prefix)
             end

  # Update our local copy with any partial information that was returned
  # from the server, ignoring an "bad" attributes that aren't defined in
  # our schema.
  response.each do |key, value|
    update_attribute(key, value) if attribute?(key)
  end

  true
end

#to_hashHash

The hash representation of this resource. All attributes are serialized and any values that respond to to_hash are also serialized.

Returns:

  • (Hash)


919
920
921
922
923
924
925
# File 'lib/chef-api/resources/base.rb', line 919

def to_hash
  {}.tap do |hash|
    _attributes.each do |key, value|
      hash[key] = value.respond_to?(:to_hash) ? value.to_hash : value
    end
  end
end

#to_jsonString

The JSON serialization of this resource.

Returns:

  • (String)


932
933
934
# File 'lib/chef-api/resources/base.rb', line 932

def to_json(*)
  JSON.fast_generate(to_hash)
end

#to_sString

Custom to_s method for easier readability.

Returns:

  • (String)


941
942
943
# File 'lib/chef-api/resources/base.rb', line 941

def to_s
  "#<#{self.class.classname} #{primary_key}: #{id.inspect}>"
end

#update(attributes = {}) ⇒ self

Update a subset of attributes on the current resource. This is a handy way to update multiple attributes at once.

Parameters:

  • attributes (Hash) (defaults to: {})

    the list of attributes to update

Returns:

  • (self)


734
735
736
737
738
739
740
# File 'lib/chef-api/resources/base.rb', line 734

def update(attributes = {})
  attributes.each do |key, value|
    update_attribute(key, value)
  end

  self
end

#update_attribute(key, value) ⇒ Object

Update a single attribute in the attributes hash.

Raises:



747
748
749
750
751
752
753
# File 'lib/chef-api/resources/base.rb', line 747

def update_attribute(key, value)
  unless attribute?(key.to_sym)
    raise Error::UnknownAttribute.new(attribute: key)
  end

  _attributes[key.to_sym] = value
end

#valid?Boolean

Determine if the current resource is valid. This relies on the validations defined in the schema at initialization.

Returns:

  • (Boolean)

    true if the resource is valid, false otherwise



794
795
796
797
798
799
800
801
802
# File 'lib/chef-api/resources/base.rb', line 794

def valid?
  errors.clear

  validators.each do |validator|
    validator.validate(self)
  end

  errors.empty?
end

#validate!Boolean

Run all of this resource’s validations, raising an exception if any validations fail.

Returns:

  • (Boolean)

    true if the validation was successful - this method will never return anything other than true because an exception is raised if validations fail

Raises:



778
779
780
781
782
783
784
785
# File 'lib/chef-api/resources/base.rb', line 778

def validate!
  unless valid?
    sentence = errors.full_messages.join(", ")
    raise Error::InvalidResource.new(errors: sentence)
  end

  true
end

#validatorsArray<~Validator::Base>

The list of validators for this resource. This is primarily set and managed by the underlying schema clean room.

Returns:



762
763
764
# File 'lib/chef-api/resources/base.rb', line 762

def validators
  @validators ||= @schema.validators
end