summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2018-02-14 11:51:42 -0800
committerGitHub <noreply@github.com>2018-02-14 11:51:42 -0800
commit2f804571812782603b027a68048b97534bcef0fc (patch)
tree61fc3ccf99d121257691fa912889178d48fd2cfb
parentc563a379b2ac9a47f5bd5c9e0c40bebed86aae8c (diff)
parent583bed675c8d928a03769c7743729eca9cfacde6 (diff)
downloadchef-2f804571812782603b027a68048b97534bcef0fc.tar.gz
Merge pull request #6846 from chef/lcg/add-nodemap-delete-class
add Chef::NodeMap#delete_class API
-rw-r--r--lib/chef/node_map.rb26
-rw-r--r--spec/unit/node_map_spec.rb29
2 files changed, 53 insertions, 2 deletions
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
index ecd5c9df8f..0406b3c1d6 100644
--- a/lib/chef/node_map.rb
+++ b/lib/chef/node_map.rb
@@ -118,6 +118,32 @@ class Chef
end.map { |matcher| matcher[:klass] }
end
+ # Remove a class from all its matchers in the node_map, will remove mappings completely if its the last matcher left
+ #
+ # Note that this leaks the internal structure out a bit, but the main consumer of this (poise/halite) cares only about
+ # the keys in the returned Hash.
+ #
+ # @param klass [Class] the class to seek and destroy
+ #
+ # @return [Hash] deleted entries in the same format as the @map
+ def delete_class(klass)
+ raise "please use a Class type for the klass argument" unless klass.is_a?(Class)
+ deleted = {}
+ map.each do |key, matchers|
+ deleted_matchers = []
+ matchers.delete_if do |matcher|
+ # because matcher[:klass] may be a string (which needs to die), coerce both to strings to compare somewhat canonically
+ if matcher[:klass].to_s == klass.to_s
+ deleted_matchers << matcher
+ true
+ end
+ end
+ deleted[key] = deleted_matchers unless deleted_matchers.empty?
+ map.delete(key) if matchers.empty?
+ end
+ deleted
+ end
+
# Seriously, don't use this, it's nearly certain to change on you
# @return remaining
# @api private
diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb
index 67bb741ec5..24f3bebe2a 100644
--- a/spec/unit/node_map_spec.rb
+++ b/spec/unit/node_map_spec.rb
@@ -19,6 +19,9 @@
require "spec_helper"
require "chef/node_map"
+class Foo; end
+class Bar; end
+
describe Chef::NodeMap do
let(:node_map) { Chef::NodeMap.new }
@@ -120,8 +123,6 @@ describe Chef::NodeMap do
end
describe "ordering classes" do
- class Foo; end
- class Bar; end
it "last writer wins when its reverse alphabetic order" do
node_map.set(:thing, Foo)
node_map.set(:thing, Bar)
@@ -135,6 +136,30 @@ describe Chef::NodeMap do
end
end
+ describe "deleting classes" do
+ it "deletes a class and removes the mapping completely" do
+ node_map.set(:thing, Bar)
+ expect( node_map.delete_class(Bar) ).to eql({ :thing => [{ :klass => Bar }] })
+ expect( node_map.get(node, :thing) ).to eql(nil)
+ end
+
+ it "deletes a class and leaves the mapping that still has an entry" do
+ node_map.set(:thing, Bar)
+ node_map.set(:thing, Foo)
+ expect( node_map.delete_class(Bar) ).to eql({ :thing => [{ :klass => Bar }] })
+ expect( node_map.get(node, :thing) ).to eql(Foo)
+ end
+
+ it "handles deleting classes from multiple keys" do
+ node_map.set(:thing1, Bar)
+ node_map.set(:thing2, Bar)
+ node_map.set(:thing2, Foo)
+ expect( node_map.delete_class(Bar) ).to eql({ :thing1 => [{ :klass => Bar }], :thing2 => [{ :klass => Bar }] })
+ expect( node_map.get(node, :thing1) ).to eql(nil)
+ expect( node_map.get(node, :thing2) ).to eql(Foo)
+ end
+ end
+
describe "with a block doing platform_version checks" do
before do
node_map.set(:thing, :foo, platform_family: "rhel") do |node|