diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/blacklist.rb | 81 | ||||
-rw-r--r-- | lib/chef/node.rb | 8 |
2 files changed, 89 insertions, 0 deletions
diff --git a/lib/chef/blacklist.rb b/lib/chef/blacklist.rb new file mode 100644 index 0000000000..a60e0318cd --- /dev/null +++ b/lib/chef/blacklist.rb @@ -0,0 +1,81 @@ + +require "chef/exceptions" + +class Chef + class Blacklist + + # filter takes two arguments - the data you want to filter, and a blacklisted array + # of keys you want discluded. You can capture a subtree of the data to filter by + # providing a "/"-delimited string of keys. If some key includes "/"-characters, + # you must provide an array of keys instead. + # + # Blacklist.filter( + # { "filesystem" => { + # "/dev/disk" => { + # "size" => "10mb" + # }, + # "map - autohome" => { + # "size" => "10mb" + # } + # }, + # "network" => { + # "interfaces" => { + # "eth0" => {...}, + # "eth1" => {...} + # } + # } + # }, + # ["network/interfaces/eth0", ["filesystem", "/dev/disk"]]) + # will exclude the eth0 and /dev/disk subtrees. + def self.filter(data, blacklist = nil) + return data if blacklist.nil? + + blacklist.each do |item| + Chef::Log.warn("Removing item #{item}") + remove_data(data, item) + end + data + end + + # Walk the data according to the keys provided by the blacklisted item + # and add the data to the whitelisting result. + def self.remove_data(data, item) + parts = to_array(item) + + item_ref = data + parts[0..-2].each do |part| + unless item_ref[part] + Chef::Log.warn("Could not find blacklist attribute #{item}.") + return nil + end + + item_ref = item_ref[part] + end + + unless item_ref.key?(parts[-1]) + Chef::Log.warn("Could not find blacklist attribute #{item}.") + return nil + end + + item_ref[parts[-1]] = nil + data + end + + private_class_method :remove_data + + # Accepts a String or an Array, and returns an Array of String keys that + # are used to traverse the data hash. Strings are split on "/", Arrays are + # assumed to contain exact keys (that is, Array elements will not be split + # by "/"). + def self.to_array(item) + return item if item.kind_of? Array + + parts = item.split("/") + parts.shift if !parts.empty? && parts[0].empty? + parts + end + + private_class_method :to_array + + end +end diff --git a/lib/chef/node.rb b/lib/chef/node.rb index 66527a2a37..1c2fbfee0f 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -34,6 +34,7 @@ require "chef/mash" require "chef/json_compat" require "chef/search/query" require "chef/whitelist" +require "chef/blacklist" class Chef class Node @@ -664,6 +665,13 @@ class Chef Chef::Log.info("Whitelisting #{level} node attributes for save.") data[level] = Chef::Whitelist.filter(data[level], whitelist) end + + blacklist_config_option = "#{level}_attribute_blacklist".to_sym + blacklist = Chef::Config[blacklist_config_option] + unless blacklist.nil? # nil => remove nothing + Chef::Log.info("Blacklisting #{level} node attributes for save") + data[level] = Chef::Blacklist.filter(data[level], blacklist) + end end data end |