Class: Chef::Node::Attribute

Inherits:
Mash
  • Object
show all
Includes:
Immutablize, Mixin::DeepMergeCache, Mixin::ImmutablizeHash, Mixin::StateTracking, Enumerable
Defined in:
lib/chef/node/attribute.rb

Overview

Attribute

Attribute implements a nested key-value (Hash) and flat collection (Array) data structure supporting multiple levels of precedence, such that a given key may have multiple values internally, but will only return the highest precedence value when reading.

Constant Summary collapse

COMPONENTS =

List of the component attribute hashes, in order of precedence, low to high.

[
  :@default,
  :@env_default,
  :@role_default,
  :@force_default,
  :@normal,
  :@override,
  :@role_override,
  :@env_override,
  :@force_override,
  :@automatic,
].freeze
DEFAULT_COMPONENTS =
[
  :@default,
  :@env_default,
  :@role_default,
  :@force_default,
]
OVERRIDE_COMPONENTS =
[
  :@override,
  :@role_override,
  :@env_override,
  :@force_override,
]

Constants included from Mixin::ImmutablizeHash

Mixin::ImmutablizeHash::ALLOWED_METHODS, Mixin::ImmutablizeHash::DISALLOWED_MUTATOR_METHODS

Instance Attribute Summary collapse

Attributes included from Mixin::StateTracking

#__node__, #__path__, #__precedence__, #__root__

Attributes included from Mixin::DeepMergeCache

#deep_merge_cache

Instance Method Summary collapse

Methods included from Mixin::StateTracking

#[], #[]=

Methods included from Mixin::DeepMergeCache

#[], #reset_cache

Methods included from Immutablize

#convert_value, #immutablize

Methods inherited from Mash

#[]=, #delete, #except, #fetch, from_hash, #initialize_copy, #internal_set, #merge, #regular_update, #regular_writer, #stringify_keys!, #symbolize_keys, #to_hash, #update, #values_at

Constructor Details

#initialize(normal, default, override, automatic, node = nil) ⇒ Attribute

Returns a new instance of Attribute.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/chef/node/attribute.rb', line 190

def initialize(normal, default, override, automatic, node = nil)
  @default        = VividMash.new(default, self, node, :default)
  @env_default    = VividMash.new({}, self, node, :env_default)
  @role_default   = VividMash.new({}, self, node, :role_default)
  @force_default  = VividMash.new({}, self, node, :force_default)

  @normal         = VividMash.new(normal, self, node, :normal)

  @override       = VividMash.new(override, self, node, :override)
  @role_override  = VividMash.new({}, self, node, :role_override)
  @env_override   = VividMash.new({}, self, node, :env_override)
  @force_override = VividMash.new({}, self, node, :force_override)

  @automatic      = VividMash.new(automatic, self, node, :automatic)

  super(nil, self, node, :merged)
end

Instance Attribute Details

#automaticObject

return the automatic level attribute component



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

def automatic
  @automatic
end

#defaultObject

return the cookbook level default attribute component



161
162
163
# File 'lib/chef/node/attribute.rb', line 161

def default
  @default
end

#env_defaultObject

return the environment level default attribute component



167
168
169
# File 'lib/chef/node/attribute.rb', line 167

def env_default
  @env_default
end

#env_overrideObject

return the enviroment level override attribute component



182
183
184
# File 'lib/chef/node/attribute.rb', line 182

def env_override
  @env_override
end

#force_defaultObject

return the force_default level attribute component



170
171
172
# File 'lib/chef/node/attribute.rb', line 170

def force_default
  @force_default
end

#force_overrideObject

return the force override level attribute component



185
186
187
# File 'lib/chef/node/attribute.rb', line 185

def force_override
  @force_override
end

#normalObject

return the “normal” level attribute component



173
174
175
# File 'lib/chef/node/attribute.rb', line 173

def normal
  @normal
end

#overrideObject

return the cookbook level override attribute component



176
177
178
# File 'lib/chef/node/attribute.rb', line 176

def override
  @override
end

#role_defaultObject

return the role level default attribute component



164
165
166
# File 'lib/chef/node/attribute.rb', line 164

def role_default
  @role_default
end

#role_overrideObject

return the role level override attribute component



179
180
181
# File 'lib/chef/node/attribute.rb', line 179

def role_override
  @role_override
end

Instance Method Details

#combined_default(*path) ⇒ Object



409
410
411
# File 'lib/chef/node/attribute.rb', line 409

def combined_default(*path)
  immutablize(merge_defaults(path))
end

#combined_override(*path) ⇒ Object



405
406
407
# File 'lib/chef/node/attribute.rb', line 405

def combined_override(*path)
  immutablize(merge_overrides(path))
end

#debug_value(*args) ⇒ Object

Debug what’s going on with an attribute. args is a path spec to the attribute you’re interested in. For example, to debug where the value of ‘node[:default_interface]` is coming from, use:

debug_value(:network, :default_interface).

The return value is an Array of Arrays. The Arrays are pairs of ‘[“precedence_level”, value]`, where precedence level is the component, such as role default, normal, etc. and value is the attribute value set at that precedence level. If there is no value at that precedence level, value will be the symbol :not_present.



217
218
219
220
221
222
223
224
225
226
227
# File 'lib/chef/node/attribute.rb', line 217

def debug_value(*args)
  COMPONENTS.map do |component|
    value =
      begin
        instance_variable_get(component).read!(*args)
      rescue
        :not_present
      end
    [component.to_s.sub(/^@/, ""), value]
  end
end

#default!(*args) ⇒ Object

sets default attributes without merging

  • this API autovivifies (and cannot trainwreck)



354
355
356
357
# File 'lib/chef/node/attribute.rb', line 354

def default!(*args)
  return Decorator::Unchain.new(self, :default!) unless args.length > 0
  write(:default, *args)
end

#default_unless(*args) ⇒ Object



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

def default_unless(*args)
  return Decorator::Unchain.new(self, :default_unless) unless args.length > 0
  write(:default, *args) if default.read(*args[0...-1]).nil?
end

#exist?(*path) ⇒ Boolean

Returns:

  • (Boolean)


443
444
445
# File 'lib/chef/node/attribute.rb', line 443

def exist?(*path)
  merged_attributes.exist?(*path)
end

#force_default!(*args) ⇒ Object

clears from all default precedence levels and then sets force_default

  • this API autovivifies (and cannot trainwreck)



378
379
380
381
382
383
# File 'lib/chef/node/attribute.rb', line 378

def force_default!(*args)
  return Decorator::Unchain.new(self, :force_default!) unless args.length > 0
  value = args.pop
  rm_default(*args)
  write(:force_default, *args, value)
end

#force_override!(*args) ⇒ Object

clears from all override precedence levels and then sets force_override



386
387
388
389
390
391
# File 'lib/chef/node/attribute.rb', line 386

def force_override!(*args)
  return Decorator::Unchain.new(self, :force_override!) unless args.length > 0
  value = args.pop
  rm_override(*args)
  write(:force_override, *args, value)
end

#has_key?(key) ⇒ Boolean Also known as: attribute?, member?, include?, key?

Returns:

  • (Boolean)


428
429
430
431
432
# File 'lib/chef/node/attribute.rb', line 428

def has_key?(key)
  COMPONENTS.any? do |component_ivar|
    instance_variable_get(component_ivar).has_key?(key)
  end
end

#inspectObject



474
475
476
477
478
# File 'lib/chef/node/attribute.rb', line 474

def inspect
  "#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv|
    "#{iv}=#{instance_variable_get(iv).inspect}"
  end.join(", ") << ">"
end

#merged_attributes(*path) ⇒ Object

Accessing merged attributes.

Note that merged_attributes(‘foo’, ‘bar’, ‘baz’) can be called to compute only the deep merge of node[‘bar’], but in practice we currently always compute all of node even if the user only requires node[’bar’].



401
402
403
# File 'lib/chef/node/attribute.rb', line 401

def merged_attributes(*path)
  merge_all(path)
end

#normal!(*args) ⇒ Object

sets normal attributes without merging

  • this API autovivifies (and cannot trainwreck)



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

def normal!(*args)
  return Decorator::Unchain.new(self, :normal!) unless args.length > 0
  write(:normal, *args)
end

#normal_unless(*args) ⇒ Object



413
414
415
416
# File 'lib/chef/node/attribute.rb', line 413

def normal_unless(*args)
  return Decorator::Unchain.new(self, :normal_unless) unless args.length > 0
  write(:normal, *args) if normal.read(*args[0...-1]).nil?
end

#override!(*args) ⇒ Object

sets override attributes without merging

  • this API autovivifies (and cannot trainwreck)



370
371
372
373
# File 'lib/chef/node/attribute.rb', line 370

def override!(*args)
  return Decorator::Unchain.new(self, :override!) unless args.length > 0
  write(:override, *args)
end

#override_unless(*args) ⇒ Object



423
424
425
426
# File 'lib/chef/node/attribute.rb', line 423

def override_unless(*args)
  return Decorator::Unchain.new(self, :override_unless) unless args.length > 0
  write(:override, *args) if override.read(*args[0...-1]).nil?
end

#read(*path) ⇒ Object

method-style access to attributes (has to come after the prepended ImmutablizeHash)



435
436
437
# File 'lib/chef/node/attribute.rb', line 435

def read(*path)
  merged_attributes.read(*path)
end

#read!(*path) ⇒ Object



439
440
441
# File 'lib/chef/node/attribute.rb', line 439

def read!(*path)
  merged_attributes.read!(*path)
end

#rm(*args) ⇒ Object

clears attributes from all precedence levels



292
293
294
295
296
297
298
# File 'lib/chef/node/attribute.rb', line 292

def rm(*args)
  with_deep_merged_return_value(self, *args) do
    rm_default(*args)
    rm_normal(*args)
    rm_override(*args)
  end
end

#rm_default(*args) ⇒ Object

clears attributes from all default precedence levels

similar to: force_default![‘bar’].delete(‘baz’)

  • does not autovivify

  • does not trainwreck if interior keys do not exist



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

def rm_default(*args)
  with_deep_merged_return_value(combined_default, *args) do
    default.unlink(*args)
    role_default.unlink(*args)
    env_default.unlink(*args)
    force_default.unlink(*args)
  end
end

#rm_normal(*args) ⇒ Object

clears attributes from normal precedence

equivalent to: normal![‘bar’].delete(‘baz’)

  • does not autovivify

  • does not trainwreck if interior keys do not exist



319
320
321
# File 'lib/chef/node/attribute.rb', line 319

def rm_normal(*args)
  normal.unlink(*args)
end

#rm_override(*args) ⇒ Object

clears attributes from all override precedence levels

equivalent to: force_override![‘bar’].delete(‘baz’)

  • does not autovivify

  • does not trainwreck if interior keys do not exist



328
329
330
331
332
333
334
335
# File 'lib/chef/node/attribute.rb', line 328

def rm_override(*args)
  with_deep_merged_return_value(combined_override, *args) do
    override.unlink(*args)
    role_override.unlink(*args)
    env_override.unlink(*args)
    force_override.unlink(*args)
  end
end

#to_sObject



470
471
472
# File 'lib/chef/node/attribute.rb', line 470

def to_s
  merged_attributes.to_s
end


455
456
457
# File 'lib/chef/node/attribute.rb', line 455

def unlink(level, *path)
  send(level).unlink(*path)
end

#unlink!(level, *path) ⇒ Object



459
460
461
# File 'lib/chef/node/attribute.rb', line 459

def unlink!(level, *path)
  send(level).unlink!(*path)
end

#write(level, *args, &block) ⇒ Object



447
448
449
# File 'lib/chef/node/attribute.rb', line 447

def write(level, *args, &block)
  send(level).write(*args, &block)
end

#write!(level, *args, &block) ⇒ Object



451
452
453
# File 'lib/chef/node/attribute.rb', line 451

def write!(level, *args, &block)
  send(level).write!(*args, &block)
end