Skip to content

Commit

Permalink
Merge pull request #1044 from juliantodt/puppet4_functions
Browse files Browse the repository at this point in the history
Use puppet4 functions-api
  • Loading branch information
eputnam authored May 24, 2018
2 parents fdc910c + c83c720 commit b8e3772
Show file tree
Hide file tree
Showing 18 changed files with 309 additions and 16 deletions.
8 changes: 4 additions & 4 deletions examples/mysql_user.pp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@

mysql_user{ 'redmine@localhost':
ensure => present,
password_hash => mysql_password('redmine'),
password_hash => mysql::password('redmine'),
require => Class['mysql::server'],
}

mysql_user{ 'dan@localhost':
ensure => present,
password_hash => mysql_password('blah')
password_hash => mysql::password('blah')
}

mysql_user{ 'dan@%':
ensure => present,
password_hash => mysql_password('blah'),
password_hash => mysql::password('blah'),
}

mysql_user{ 'socketplugin@%':
Expand All @@ -27,6 +27,6 @@

mysql_user{ 'socketplugin@%':
ensure => present,
password_hash => mysql_password('blah'),
password_hash => mysql::password('blah'),
plugin => 'mysql_native_password',
}
66 changes: 66 additions & 0 deletions lib/puppet/functions/mysql/deepmerge.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# @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.
#
Puppet::Functions.create_function(:'mysql::deepmerge') do
def 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

# We need to make a copy of the hash since it is frozen by puppet
current = deep_copy(arg)

# 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, current)
end
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

def deep_copy(inputhash)
return inputhash unless inputhash.is_a? Hash
hash = {}
inputhash.each do |k, v|
hash.store(k, deep_copy(v))
end
hash
end
end
20 changes: 20 additions & 0 deletions lib/puppet/functions/mysql/dirname.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# @summary
# Returns the dirname of a path
#
Puppet::Functions.create_function(:'mysql::dirname') do
# @param path
# Path to find the dirname for.
#
# @return
# Directory name of path.
#
dispatch :dirname do
required_param 'Variant[String, Undef]', :path
return_type 'String'
end

def dirname(path)
return '' if path.nil?
File.dirname(path)
end
end
21 changes: 21 additions & 0 deletions lib/puppet/functions/mysql/password.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'digest/sha1'
# @summary
# Hash a string as mysql's "PASSWORD()" function would do it
#
Puppet::Functions.create_function(:'mysql::password') do
# @param password
# Plain text password.
#
# @return the mysql password hash from the clear text password.
#
dispatch :password do
required_param 'String', :password
return_type 'String'
end

def password(password)
return '' if password.empty?
return password if password =~ %r{\*[A-F0-9]{40}$}
'*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(password)).upcase
end
end
19 changes: 19 additions & 0 deletions lib/puppet/functions/mysql/strip_hash.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# @summary
# When given a hash this function strips out all blank entries.
#
Puppet::Functions.create_function(:'mysql::strip_hash') do
# @param hash
# Hash to be stripped
#
dispatch :strip_hash do
required_param 'Hash', :hash
return_type 'Hash'
end

def strip_hash(hash)
# Filter out all the top level blanks.
hash.reject { |_k, v| v == '' }.each do |_k, v|
v.reject! { |_ki, vi| vi == '' } if v.is_a?(Hash)
end
end
end
4 changes: 2 additions & 2 deletions manifests/backup/mysqlbackup.pp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

mysql_user { "${backupuser}@localhost":
ensure => $ensure,
password_hash => mysql_password($backuppassword),
password_hash => mysql::password($backuppassword),
require => Class['mysql::server::root_password'],
}

Expand Down Expand Up @@ -92,7 +92,7 @@
'password' => $backuppassword,
}
}
$options = mysql_deepmerge($default_options, $mysql::server::override_options)
$options = mysql::deepmerge($default_options, $mysql::server::override_options)

file { 'mysqlbackup-config-file':
path => '/etc/mysql/conf.d/meb.cnf',
Expand Down
2 changes: 1 addition & 1 deletion manifests/backup/mysqldump.pp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

mysql_user { "${backupuser}@localhost":
ensure => $ensure,
password_hash => mysql_password($backuppassword),
password_hash => mysql::password($backuppassword),
require => Class['mysql::server::root_password'],
}

Expand Down
2 changes: 1 addition & 1 deletion manifests/backup/xtrabackup.pp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
if $backupuser and $backuppassword {
mysql_user { "${backupuser}@localhost":
ensure => $ensure,
password_hash => mysql_password($backuppassword),
password_hash => mysql::password($backuppassword),
require => Class['mysql::server::root_password'],
}

Expand Down
2 changes: 1 addition & 1 deletion manifests/db.pp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@

$user_resource = {
ensure => $ensure,
password_hash => mysql_password($password),
password_hash => mysql::password($password),
}
ensure_resource('mysql_user', "${user}@${host}", $user_resource)

Expand Down
2 changes: 1 addition & 1 deletion manifests/server.pp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
}

# Create a merged together set of options. Rightmost hashes win over left.
$options = mysql_deepmerge($mysql::params::default_options, $override_options)
$options = mysql::deepmerge($mysql::params::default_options, $override_options)

Class['mysql::server::root_password'] -> Mysql::Db <| |>

Expand Down
2 changes: 1 addition & 1 deletion manifests/server/binarylog.pp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
$logbin = pick($options['mysqld']['log-bin'], $options['mysqld']['log_bin'], false)

if $logbin {
$logbindir = mysql_dirname($logbin)
$logbindir = mysql::dirname($logbin)

#Stop puppet from managing directory if just a filename/prefix is specified
if $logbindir != '.' {
Expand Down
6 changes: 3 additions & 3 deletions manifests/server/config.pp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

# on some systems this is /etc/my.cnf.d, while Debian has /etc/mysql/conf.d and FreeBSD something in /usr/local. For the latter systems,
# managing this basedir is also required, to have it available before the package is installed.
$includeparentdir = mysql_dirname($includedir)
$includeparentdir = mysql::dirname($includedir)
if $includeparentdir != '/' and $includeparentdir != '/etc' {
file { $includeparentdir:
ensure => directory,
Expand All @@ -43,9 +43,9 @@

# on mariadb systems, $includedir is not defined, but /etc/my.cnf.d has
# to be managed to place the server.cnf there
$configparentdir = mysql_dirname($mysql::server::config_file)
$configparentdir = mysql::dirname($mysql::server::config_file)
if $configparentdir != '/' and $configparentdir != '/etc' and $configparentdir
!= $includedir and $configparentdir != mysql_dirname($includedir) {
!= $includedir and $configparentdir != mysql::dirname($includedir) {
file { $configparentdir:
ensure => directory,
mode => '0755',
Expand Down
2 changes: 1 addition & 1 deletion manifests/server/monitor.pp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

mysql_user { "${mysql_monitor_username}@${mysql_monitor_hostname}":
ensure => present,
password_hash => mysql_password($mysql_monitor_password),
password_hash => mysql::password($mysql_monitor_password),
require => Class['mysql::server::service'],
}

Expand Down
2 changes: 1 addition & 1 deletion manifests/server/root_password.pp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
if $mysql::server::create_root_user == true and $mysql::server::root_password != 'UNSET' {
mysql_user { 'root@localhost':
ensure => present,
password_hash => mysql_password($mysql::server::root_password),
password_hash => mysql::password($mysql::server::root_password),
require => Exec['remove install pass']
}
}
Expand Down
94 changes: 94 additions & 0 deletions spec/functions/mysql_deepmerge_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#! /usr/bin/env ruby -S rspec # rubocop:disable Lint/ScriptPermission

require 'spec_helper'

describe 'mysql::deepmerge' do
it 'exists' do
is_expected.not_to eq(nil)
end

it 'throws error with no arguments' do
is_expected.to run.with_params.and_raise_error(Puppet::ParseError)
end

it 'throws error with only one argument' do
is_expected.to run.with_params('one' => 1).and_raise_error(Puppet::ParseError)
end

it 'accepts empty strings as puppet undef' do
is_expected.to run.with_params({}, '')
end

# rubocop:disable RSpec/NamedSubject
index_values = %w[one two three]
expected_values_one = %w[1 2 2]
it 'is able to mysql_deepmerge two hashes' do
new_hash = subject.execute({ 'one' => '1', 'two' => '1' }, 'two' => '2', 'three' => '2')
index_values.each_with_index do |index, expected|
expect(new_hash[index]).to eq(expected_values_one[expected])
end
end

it 'mysql_deepmerges multiple hashes' do
hash = subject.execute({ 'one' => 1 }, { 'one' => '2' }, 'one' => '3')
expect(hash['one']).to eq('3')
end

it 'accepts empty hashes' do
is_expected.to run.with_params({}, {}, {}).and_return({})
end

expected_values_two = [1, 2, 'four' => 4]
it 'mysql_deepmerges subhashes' do
hash = subject.execute({ 'one' => 1 }, 'two' => 2, 'three' => { 'four' => 4 })
index_values.each_with_index do |index, expected|
expect(hash[index]).to eq(expected_values_two[expected])
end
end

it 'appends to subhashes' do
hash = subject.execute({ 'one' => { 'two' => 2 } }, 'one' => { 'three' => 3 })
expect(hash['one']).to eq('two' => 2, 'three' => 3)
end

expected_values_three = [1, 'dos', { 'four' => 4, 'five' => 5 }]
it 'appends to subhashes 2' do
hash = subject.execute({ 'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }, 'two' => 'dos', 'three' => { 'five' => 5 })
index_values.each_with_index do |index, expected|
expect(hash[index]).to eq(expected_values_three[expected])
end
end

index_values_two = %w[key1 key2]
expected_values_four = [{ 'a' => 1, 'b' => 99 }, 'c' => 3]
it 'appends to subhashes 3' do
hash = subject.execute({ 'key1' => { 'a' => 1, 'b' => 2 }, 'key2' => { 'c' => 3 } }, 'key1' => { 'b' => 99 })
index_values_two.each_with_index do |index, expected|
expect(hash[index]).to eq(expected_values_four[expected])
end
end

it 'equates keys mod dash and underscore #value' do
hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10)
expect(hash['a_b_c']).to eq(10)
end
it 'equates keys mod dash and underscore #not' do
hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10)
expect(hash).not_to have_key('a-b-c')
end

index_values_three = ['a_b_c', 'b-c-d']
expected_values_five = [10, { 'e-f-g' => 3, 'c_d_e' => 12 }]
index_values_error = ['a-b-c', 'b_c_d']
index_values_three.each_with_index do |index, expected|
it 'keeps style of the last when keys are equal mod dash and underscore #value' do
hash = subject.execute({ 'a-b-c' => 1, 'b_c_d' => { 'c-d-e' => 2, 'e-f-g' => 3 } }, 'a_b_c' => 10, 'b-c-d' => { 'c_d_e' => 12 })
expect(hash[index]).to eq(expected_values_five[expected])
end
it 'keeps style of the last when keys are equal mod dash and underscore #not' do
hash = subject.execute({ 'a-b-c' => 1, 'b_c_d' => { 'c-d-e' => 2, 'e-f-g' => 3 } }, 'a_b_c' => 10, 'b-c-d' => { 'c_d_e' => 12 })
expect(hash).not_to have_key(index_values_error[expected])
end
end
# rubocop:enable RSpec/NamedSubject
end
19 changes: 19 additions & 0 deletions spec/functions/mysql_dirname_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'spec_helper'

describe 'mysql::dirname' do
it 'exists' do
is_expected.not_to eq(nil)
end

it 'raises a ArgumentError if there is less than 1 arguments' do
is_expected.to run.with_params.and_raise_error(ArgumentError)
end

it 'raises a ArgumentError if there is more than 1 arguments' do
is_expected.to run.with_params('foo', 'bar').and_raise_error(ArgumentError)
end

it 'returns path of file' do
is_expected.to run.with_params('spec/functions/mysql_dirname_spec.rb').and_return('spec/functions')
end
end
Loading

0 comments on commit b8e3772

Please sign in to comment.