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:



548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
# File 'lib/chef-api/resources/base.rb', line 548

def initialize(attributes = {}, prefix = {})
  @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)


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

def associations
  @associations
end

Class Method Details

.allArray<Resource::Base>

Return an array of all resources in the collection.

Returns:



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

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:



273
274
275
# File 'lib/chef-api/resources/base.rb', line 273

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

.classnameString

The name for this resource, minus the parent module.

Examples:

classname #=> Resource::Bacon

Returns:

  • (String)


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

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:



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

def collection(prefix = {})
  ChefAPI.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



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

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

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

The total number of reosurces in the collection.

Returns:

  • (Fixnum)


378
379
380
# File 'lib/chef-api/resources/base.rb', line 378

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:



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

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)


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

def delete(id, prefix = {})
  path = resource_path(id, prefix)
  ChefAPI.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



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

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



229
230
231
# File 'lib/chef-api/resources/base.rb', line 229

def destroy_all(prefix = {})
  map { |resource| resource.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"]


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

def each(prefix = {}, &block)
  collection(prefix).each do |resource, path|
    response = ChefAPI.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:



314
315
316
# File 'lib/chef-api/resources/base.rb', line 314

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:



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

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

    URI.escape(value)
  end.sub(/^\//, '') # 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



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

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

  path     = resource_path(id, prefix)
  response = ChefAPI.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:



15
16
17
# File 'lib/chef-api/resources/base.rb', line 15

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



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

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

  new(response, prefix)
end

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



22
23
24
# File 'lib/chef-api/resources/base.rb', line 22

def from_url(url, prefix = {})
  from_json(ChefAPI.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'


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

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

  class_eval <<-EOH, __FILE__, __LINE__ + 1
    def #{method}
      associations[:#{method}] ||=
        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)


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

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


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

def list(prefix = {})
  path = expanded_collection_path(prefix)
  ChefAPI.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



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

def post(body, prefix = {})
  path = expanded_collection_path(prefix)
  ChefAPI.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



64
65
66
# File 'lib/chef-api/resources/base.rb', line 64

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

.protected_resourcesObject



95
96
97
# File 'lib/chef-api/resources/base.rb', line 95

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



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

def put(id, body, prefix = {})
  path = resource_path(id, prefix)
  ChefAPI.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



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

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



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

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)


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

def to_s
  classname
end

.typeString

The type of this resource.

Examples:

bacon

Returns:

  • (String)


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

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:



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

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


598
599
600
# File 'lib/chef-api/resources/base.rb', line 598

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

#_prefixObject



589
590
591
# File 'lib/chef-api/resources/base.rb', line 589

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



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

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

#destroyself

Remove the resource from the Chef Server.

Returns:

  • (self)

    the current instance of this object



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

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

#diffHash

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)


853
854
855
856
857
858
859
860
861
862
863
864
# File 'lib/chef-api/resources/base.rb', line 853

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



831
832
833
# File 'lib/chef-api/resources/base.rb', line 831

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

#errorsErrorCollection

The collection of errors on the resource.

Returns:



898
899
900
# File 'lib/chef-api/resources/base.rb', line 898

def errors
  @errors ||= ErrorCollection.new
end

#idObject

The unique id for this resource.

Returns:

  • (Object)


582
583
584
# File 'lib/chef-api/resources/base.rb', line 582

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:



889
890
891
# File 'lib/chef-api/resources/base.rb', line 889

def ignore_attribute?(key)
  self.class.schema.ignored_attributes.has_key?(key.to_sym)
end

#inspectString

Custom inspect method for easier readability.

Returns:

  • (String)


939
940
941
942
943
944
945
946
947
948
949
# File 'lib/chef-api/resources/base.rb', line 939

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



808
809
810
# File 'lib/chef-api/resources/base.rb', line 808

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



573
574
575
# File 'lib/chef-api/resources/base.rb', line 573

def primary_key
  self.class.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:



623
624
625
626
627
628
629
630
631
# File 'lib/chef-api/resources/base.rb', line 623

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

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



645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/chef-api/resources/base.rb', line 645

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



876
877
878
# File 'lib/chef-api/resources/base.rb', line 876

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



696
697
698
699
700
# File 'lib/chef-api/resources/base.rb', line 696

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



669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
# File 'lib/chef-api/resources/base.rb', line 669

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)


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

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)


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

def to_json
  JSON.fast_generate(to_hash)
end

#to_sString

Custom to_s method for easier readability.

Returns:

  • (String)


930
931
932
# File 'lib/chef-api/resources/base.rb', line 930

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)


722
723
724
725
726
727
728
# File 'lib/chef-api/resources/base.rb', line 722

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:



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

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



782
783
784
785
786
787
788
789
790
# File 'lib/chef-api/resources/base.rb', line 782

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:



766
767
768
769
770
771
772
773
# File 'lib/chef-api/resources/base.rb', line 766

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:



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

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