-
Notifications
You must be signed in to change notification settings - Fork 795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(FM-7547) move function definitions out of Puppet function #1139
(FM-7547) move function definitions out of Puppet function #1139
Conversation
In Puppet 5.5.7, legacy functions that had ruby functions defined in the file no longer work. This puts it into a library class.
@hlindberg Is this the recommended solution? |
Best is to implement this using the 4x function API and have the extra methods inside the function body. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to using the 4x function API - you can then keep the extra methods inside the function definition.
Should the FM ticket be moved to MODULES (and this PR updated) since only MODULES is public? |
kk. Porting to the new API is a little more work than I've got time for today. Someone else should pick this up and run with it then :) |
It is really easy to convert to 4.x - Here is the code (without using any refactoring other than making it be implemented with the 4x API). Simply put this in # @summary Recursively merges two or more hashes together and returns the resulting hash.
#
# @example
# $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
# $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
# $merged_hash = mysql_deepmerge($hash1, $hash2)
# # The resulting hash is equivalent to:
# # $merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
#
# - When there is a duplicate key that is a hash, they are recursively merged.
# - When there is a duplicate key that is not a hash, the key in the rightmost hash will "win."
# - When there are conficting uses of dashes and underscores in two keys (which mysql would otherwise equate),
# the rightmost style will win.
#
# @return [Hash]
#
Puppet::Functions.create_function(:mysql_deepmerge) do
dispatch :mysql_deepmerge do
repeated_param 'Any', :args
end
def mysql_deepmerge(args)
if args.length < 2
raise Puppet::ParseError, _('mysql_deepmerge(): wrong number of arguments (%{args_length}; must be at least 2)') % { args_length: args.length }
end
result = {}
args.each do |arg|
next if arg.is_a?(String) && arg.empty? # empty string is synonym for puppet's undef
# If the argument was not a hash, skip it.
unless arg.is_a?(Hash)
raise Puppet::ParseError, _('mysql_deepmerge: unexpected argument type %{arg_class}, only expects hash arguments.') % { args_class: args.class }
end
# Now we have to traverse our hash assigning our non-hash values
# to the matching keys in our result while following our hash values
# and repeating the process.
overlay(result, arg)
end
return(result)
end
def normalized?(hash, key)
return true if hash.key?(key)
return false unless key =~ %r{-|_}
other_key = key.include?('-') ? key.tr('-', '_') : key.tr('_', '-')
return false unless hash.key?(other_key)
hash[key] = hash.delete(other_key)
true
end
def overlay(hash1, hash2)
hash2.each do |key, value|
if normalized?(hash1, key) && value.is_a?(Hash) && hash1[key].is_a?(Hash)
overlay(hash1[key], value)
else
hash1[key] = value
end
end
end
end As you can see - any 3.x function is trivially changed to 4.x by making it have a dispatcher accepting a variable number of Any arguments, then wrapping the function's code in a Naturally more refactoring is possible since checking of the input parameters can be delegated to the dispatcher - but I did not spend time figuring out what this function actually accepts. You may need adjustments to the testing of the function - I did not look at that... |
@hlindberg actually, I just realized that all that work has been done. https://github.com/puppetlabs/puppetlabs-mysql/blob/master/lib/puppet/functions/mysql/deepmerge.rb These legacy functions are to keep from breaking existing code. |
This reverts commit e8b5f84.
This function breaks with a non-helpful error message on Puppet 5.5.7. Perhaps we should just raise an upgrade error instead.
@HelenCampbell Is this a good idea? |
Looks good @binford2k ! I'd suggest looking in to using the deprecation function in stdlib to see if it'd makes sense to use it for this as it can be turned off by users (I'll link it below), but otherwise I'm happy with this change 👍 |
@HelenCampbell I think this has to be a hard failure, because if the loader loads the file, then it crashes before the function is executed. Also, I'm not sure what to do about the test that's failing (appropriately). As soon as the spec loads, it will load the file and raise the exception. @hlindberg, do you have suggestions here? (besides burn it with 🔥) |
@binford2k the 4x version of the function has a different name and requires users to shift to using it. Why not let it have the same name as the 3.x version (i.e. not namespaced). That way the 3.x version of the function will never be loaded. If you want to deprecate the non namespaced, then add a 4.x function that performs the deprecation - it can naturally also call the namespaced version. After that, the only reason to keep the 3.x version of the function is to support Puppet < 4.0.0 |
Maybe my earlier comment was not that clear - what I am suggesting is:
Then, if there are tests that rely on |
@binford2k I am closing this PR as the function that it references, 'deep_merge', has since been removed from the code in #1145 as it is a copy of a function that exist's within puppet itself. |
In Puppet 5.5.7, legacy functions that had ruby functions defined in the
file no longer work. This puts it into a library class.