diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2018-02-23 11:20:50 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2018-02-23 11:20:50 -0800 |
commit | c60c5009e887e650c747581f90b6c68dfae44234 (patch) | |
tree | 12a0691332a1bdffeebb70915884cad8fe85da8a /lib/chef/node/attribute.rb | |
parent | a50bfb54e2d570c73cf44cd021432e689e8efbe8 (diff) | |
download | chef-c60c5009e887e650c747581f90b6c68dfae44234.tar.gz |
Revert "Per-container deep merge caching"lcg/revert-lazy-attributes
This reverts commit 0c29acc106ca774e230c8ef45694c8bffd166b69.
Diffstat (limited to 'lib/chef/node/attribute.rb')
-rw-r--r-- | lib/chef/node/attribute.rb | 118 |
1 files changed, 70 insertions, 48 deletions
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb index debb3eeaef..cd6061e24f 100644 --- a/lib/chef/node/attribute.rb +++ b/lib/chef/node/attribute.rb @@ -17,7 +17,7 @@ # limitations under the License. # -#require "chef/node/mixin/deep_merge_cache" +require "chef/node/mixin/deep_merge_cache" require "chef/node/mixin/immutablize_hash" require "chef/node/mixin/state_tracking" require "chef/node/immutable_collections" @@ -45,7 +45,7 @@ class Chef # expects. This include should probably be deleted? include Enumerable - #include Chef::Node::Mixin::DeepMergeCache + include Chef::Node::Mixin::DeepMergeCache include Chef::Node::Mixin::StateTracking include Chef::Node::Mixin::ImmutablizeHash @@ -187,9 +187,6 @@ class Chef # return the automatic level attribute component attr_reader :automatic - # return the immutablemash deep merge cache - attr_reader :deep_merge_cache - def initialize(normal, default, override, automatic, node = nil) @default = VividMash.new(default, self, node, :default) @env_default = VividMash.new({}, self, node, :env_default) @@ -205,8 +202,7 @@ class Chef @automatic = VividMash.new(automatic, self, node, :automatic) - @deep_merge_cache = ImmutableMash.new({}, self, node, :merged) - @__node__ = node + super(nil, self, node, :merged) end # Debug what's going on with an attribute. +args+ is a path spec to the @@ -230,22 +226,6 @@ class Chef end end - def reset - @deep_merge_cache = ImmutableMash.new({}, self, @__node__, :merged) - end - - def reset_cache(*path) - if path.empty? - reset - else - container = read(*path) - case container - when Hash, Array - container.reset - end - end - end - # Set the cookbook level default attribute component to +new_data+. def default=(new_data) reset @@ -310,7 +290,7 @@ class Chef # clears attributes from all precedence levels def rm(*args) - with_deep_merged_return_value(combined_all, *args) do + with_deep_merged_return_value(self, *args) do rm_default(*args) rm_normal(*args) rm_override(*args) @@ -357,9 +337,6 @@ class Chef def with_deep_merged_return_value(obj, *path, last) hash = obj.read(*path) return nil unless hash.is_a?(Hash) - # coerce from immutablemash/vividmash to plain-old Hash - # also de-immutablizes and dup's the return value correctly in chef-13 - hash = hash.to_hash ret = hash[last] yield ret @@ -421,16 +398,16 @@ class Chef # all of node['foo'] even if the user only requires node['foo']['bar']['baz']. # - def combined_override(*path) - merge_overrides(path) + def merged_attributes(*path) + merge_all(path) end - def combined_all(*path) - path.empty? ? self : read(*path) + def combined_override(*path) + immutablize(merge_overrides(path)) end def combined_default(*path) - merge_defaults(path) + immutablize(merge_defaults(path)) end def normal_unless(*args) @@ -494,14 +471,6 @@ class Chef merged_attributes.to_s end - def [](key) - @deep_merge_cache[key] - end - - def merged_attributes - @deep_merge_cache - end - def inspect "#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv| "#{iv}=#{instance_variable_get(iv).inspect}" @@ -510,14 +479,7 @@ class Chef private - # For elements like Fixnums, true, nil... - def safe_dup(e) - e.dup - rescue TypeError - e - end - - # Helper method for merge_defaults/merge_overrides. + # Helper method for merge_all/merge_defaults/merge_overrides. # # apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"] # @@ -547,6 +509,34 @@ class Chef end end + # For elements like Fixnums, true, nil... + def safe_dup(e) + e.dup + rescue TypeError + e + end + + # Deep merge all attribute levels using hash-only merging between different precidence + # levels (so override arrays completely replace arrays set at any default level). + # + # The path allows for selectively deep-merging a subtree of the node object. + # + # @param path [Array] Array of args to method chain to descend into the node object + # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object + def merge_all(path) + components = [ + merge_defaults(path), + apply_path(@normal, path), + merge_overrides(path), + apply_path(@automatic, path), + ] + + ret = components.inject(NIL) do |merged, component| + hash_only_merge!(merged, component) + end + ret == NIL ? nil : ret + end + # Deep merge the default attribute levels with array merging. # # The path allows for selectively deep-merging a subtree of the node object. @@ -618,6 +608,38 @@ class Chef end end + # @api private + def hash_only_merge!(merge_onto, merge_with) + # If there are two Hashes, recursively merge. + if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash) + merge_with.each do |key, merge_with_value| + value = + if merge_onto.has_key?(key) + hash_only_merge!(safe_dup(merge_onto[key]), merge_with_value) + else + merge_with_value + end + + # internal_set bypasses converting keys, does convert values and allows writing to immutable mashes + merge_onto.internal_set(key, value) + end + merge_onto + + # If merge_with is nil, don't replace merge_onto + elsif merge_with.nil? + merge_onto + + # In all other cases, replace merge_onto with merge_with + else + if merge_with.kind_of?(Hash) + Chef::Node::ImmutableMash.new(merge_with) + elsif merge_with.kind_of?(Array) + Chef::Node::ImmutableArray.new(merge_with) + else + merge_with + end + end + end end end end |