summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoah Kantrowitz <noah@coderanger.net>2018-05-04 17:11:25 -0700
committerNoah Kantrowitz <noah@coderanger.net>2018-06-05 20:25:11 -0700
commit8e7800ab9c51e256d85722fd58c1cf8e27bb5a96 (patch)
tree98f5e49c2e988a231656102903cca1b7991ec3c7
parent9138b6da9f344f77c574e939de387590ff284eba (diff)
downloadchef-8e7800ab9c51e256d85722fd58c1cf8e27bb5a96.tar.gz
First pass on an implementation for https://github.com/chef/chef-rfc/pull/305
Signed-off-by: Noah Kantrowitz <noah@coderanger.net>
-rw-r--r--lib/chef/client.rb3
-rw-r--r--lib/chef/node_map.rb46
2 files changed, 48 insertions, 1 deletions
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 7218c3bb49..33d625c54e 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -275,6 +275,9 @@ class Chef
do_windows_admin_check
+ Chef.resource_handler_map.lock!
+ Chef.provider_handler_map.lock!
+
run_context = setup_run_context
load_required_recipe(@rest, run_context) unless Chef::Config[:solo_legacy_mode]
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
index 0406b3c1d6..448e695ca9 100644
--- a/lib/chef/node_map.rb
+++ b/lib/chef/node_map.rb
@@ -45,12 +45,16 @@ class Chef
# @param key [Object] Key to store
# @param value [Object] Value associated with the key
# @param filters [Hash] Node filter options to apply to key retrieval
+ # @param allow_cookbook_override [Boolean] Allow a cookbook to add to this
+ # key even in locked mode.
+ # @param __core_override__ [Boolean] Advanced-mode override to add to a key
+ # even in locked mode.
#
# @yield [node] Arbitrary node filter as a block which takes a node argument
#
# @return [NodeMap] Returns self for possible chaining
#
- def set(key, klass, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block)
+ def set(key, klass, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, allow_cookbook_override: false, __core_override__: false, &block)
new_matcher = { klass: klass }
new_matcher[:platform] = platform if platform
new_matcher[:platform_version] = platform_version if platform_version
@@ -59,6 +63,18 @@ class Chef
new_matcher[:block] = block if block
new_matcher[:canonical] = canonical if canonical
new_matcher[:override] = override if override
+ new_matcher[:cookbook_override] = allow_cookbook_override
+ new_matcher[:core_override] = __core_override__
+
+ # Check if the key is already present and locked, unless the override is allowed.
+ if !__core_override__ && map[key] && map[key].any? {|matcher| matcher[:locked] } && !map[key].any? {|matcher| matcher[:cookbook_override] }
+ type_of_thing = klass.is_a?(Chef::Resource) ? 'resource' : 'provider'
+ # For now, only log the warning.
+ Chef.log_deprecation("Trying to register #{type_of_thing} #{key} on top of existing Chef core #{type_of_thing}. Check if a new version of the cookbook is available.")
+ # In 15.0, uncomment this and remove the log above.
+ # Chef.log_deprecation("Rejecting attempt to register #{type_of_thing} #{key} on top of existing Chef core #{type_of_thing}. Check if a new version of the cookbook is available.")
+ # return
+ end
# The map is sorted in order of preference already; we just need to find
# our place in it (just before the first value with the same preference level).
@@ -159,6 +175,34 @@ class Chef
remaining
end
+ # Check if this map has been locked.
+ #
+ # @api internal
+ # @since 14.2
+ # @return [Boolean]
+ def locked?
+ if defined?(@locked)
+ @locked
+ else
+ false
+ end
+ end
+
+ # Set this map to locked mode. This is used to prevent future overwriting
+ # of existing names.
+ #
+ # @api internal
+ # @since 14.2
+ # @return [void]
+ def lock!
+ map.each do |key, matchers|
+ matchers.each do |matcher|
+ matcher[:locked] = true
+ end
+ end
+ @locked = true
+ end
+
private
#