Skip to content

Instantly share code, notes, and snippets.

@rdark
Created October 24, 2014 13:59
Show Gist options
  • Save rdark/c70791321e9800cb816f to your computer and use it in GitHub Desktop.
Save rdark/c70791321e9800cb816f to your computer and use it in GitHub Desktop.
delete_nested_subkeys
#
# delete_child_subkey.rb
#
# === Author
#
# Richard Clark <richard@fohnet.co.uk>
#
module Puppet::Parser::Functions
newfunction(:delete_child_subkey, :type => :rvalue, :doc => <<-EOS
Given a hash containing nested hashes, a single or array of regular
expressions, and a single, or array of third-depth keys to match, this function
will delete those keys from second level hash structure, where those second
level keys match any of the given regular expressions
This is primarily intended for sharing hiera data structures between multiple
classes that require similar, but not identical data in order to pass back to a
define/defined type using create_resouces or equivilant.
Anything that is not a nested hash, or does not match the regular expression is passed to the output without processing further.
See also: insert_child_subkey(), delete()
*Examples:*
A given variable $hiera_puppet_modules which contains a hash:
hiera_puppet_modules = {
'puppet_module_vsftpd' => {
'ensure' => 'present',
'git_repo' => 'git@git.mydomain',
'branch' => 'production',
'unwanted' => 'data',
},
'puppet_module_this' => 'that',
'array_of_data' => [ 'some', 'things' ],
'my_code_repo' => {
'ensure' => 'present',
'git_repo' => 'git@git.mydomain',
'branch' => 'production',
'spurious' => 'data',
'unwanted' => 'data',
},
'puppet_module_apache' => {
'ensure' => 'present',
'git_repo' => 'git@git.mydomain',
'branch' => 'production',
'spurious' => 'data',
}
}
A regular expession matching: '^puppet_module_'
And a set of subkeys matching: ['git_repo', 'branch', 'spurious', 'data' ]
Passed to this function as: delete_child_subkey(
$hiera_puppet_modules,
'^puppet_module_',
['git_repo', 'branch', 'spurious', 'data' ]
)
Would give:
hiera_puppet_modules = {
'puppet_module_vsftpd' => {
'ensure' => 'present',
},
'puppet_module_this' => 'that',
'array_of_data' => [ 'some', 'things' ],
'my_code_repo' => {
'ensure' => 'present',
'git_repo' => 'git@git.mydomain',
'branch' => 'production',
'spurious' => 'data',
'unwanted' => 'data',
},
'puppet_module_apache' => {
'ensure' => 'present',
}
}
EOS
) do |arguments|
if (arguments.size != 3) then
raise(Puppet::ParseError, "delete_child_subkey(): Wrong number of arguments "+
"given #{arguments.size} for 3.")
end
src_hash = arguments[0]
regex = arguments[1]
del_key = arguments[2]
unless src_hash.is_a?(Hash)
raise Puppet::ParseError, "First argument must be a hash"
end
unless regex.is_a?(String) or regex.is_a?(Array)
raise Puppet::ParseError, "Second argument must be a single or array of string-format regex"
end
unless del_key.is_a?(String) or del_key.is_a?(Array)
raise Puppet::ParseError, "Third argument must be a single or array of keys to delete at third level depth"
end
# transform regex + del_key into arrays if they are not already
regex = [ regex ] if regex.is_a?(String)
del_key = [ del_key ] if del_key.is_a?(String)
# destination hash to store wanted data structure
dest_hash = Hash.new
# get second level keys
src_hash.keys.each do |parent|
# if it's not a hash, just insert it and move on
unless src_hash[parent].is_a?(Hash)
dest_hash[parent] = src_hash[parent]
next
end
# create empty hash nested at parent in destination hash
dest_hash[parent] = Hash.new
src_hash[parent].keys.each do |child|
regex.each do |r|
if parent !~ /#{r}/
# if we don't match the regex, insert the values and move on
dest_hash[parent][child] = src_hash[parent][child]
break
else
# otherwise we match, so insert the keys, but only if they're on in
# the del_key list
dest_hash[parent][child] = src_hash[parent][child] unless del_key.include?(child)
break
end
end
end
end
dest_hash
end
end
# vim: set ts=2 sw=2 et :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment