diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2018-02-14 11:51:42 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-14 11:51:42 -0800 |
commit | 2f804571812782603b027a68048b97534bcef0fc (patch) | |
tree | 61fc3ccf99d121257691fa912889178d48fd2cfb | |
parent | c563a379b2ac9a47f5bd5c9e0c40bebed86aae8c (diff) | |
parent | 583bed675c8d928a03769c7743729eca9cfacde6 (diff) | |
download | chef-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.rb | 26 | ||||
-rw-r--r-- | spec/unit/node_map_spec.rb | 29 |
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| |