Skip to content

Commit b8e3772

Browse files
authored
Merge pull request #1044 from juliantodt/puppet4_functions
Use puppet4 functions-api
2 parents fdc910c + c83c720 commit b8e3772

18 files changed

+309
-16
lines changed

examples/mysql_user.pp

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66

77
mysql_user{ 'redmine@localhost':
88
ensure => present,
9-
password_hash => mysql_password('redmine'),
9+
password_hash => mysql::password('redmine'),
1010
require => Class['mysql::server'],
1111
}
1212

1313
mysql_user{ 'dan@localhost':
1414
ensure => present,
15-
password_hash => mysql_password('blah')
15+
password_hash => mysql::password('blah')
1616
}
1717

1818
mysql_user{ 'dan@%':
1919
ensure => present,
20-
password_hash => mysql_password('blah'),
20+
password_hash => mysql::password('blah'),
2121
}
2222

2323
mysql_user{ 'socketplugin@%':
@@ -27,6 +27,6 @@
2727

2828
mysql_user{ 'socketplugin@%':
2929
ensure => present,
30-
password_hash => mysql_password('blah'),
30+
password_hash => mysql::password('blah'),
3131
plugin => 'mysql_native_password',
3232
}
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# @summary Recursively merges two or more hashes together and returns the resulting hash.
2+
#
3+
# @example
4+
# $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
5+
# $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
6+
# $merged_hash = mysql_deepmerge($hash1, $hash2)
7+
# # The resulting hash is equivalent to:
8+
# # $merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
9+
#
10+
# - When there is a duplicate key that is a hash, they are recursively merged.
11+
# - When there is a duplicate key that is not a hash, the key in the rightmost hash will "win."
12+
# - When there are conficting uses of dashes and underscores in two keys (which mysql would otherwise equate), the rightmost style will win.
13+
#
14+
Puppet::Functions.create_function(:'mysql::deepmerge') do
15+
def deepmerge(*args)
16+
if args.length < 2
17+
raise Puppet::ParseError, _('mysql_deepmerge(): wrong number of arguments (%{args_length}; must be at least 2)') % { args_length: args.length }
18+
end
19+
20+
result = {}
21+
args.each do |arg|
22+
next if arg.is_a?(String) && arg.empty? # empty string is synonym for puppet's undef
23+
# If the argument was not a hash, skip it.
24+
unless arg.is_a?(Hash)
25+
raise Puppet::ParseError, _('mysql_deepmerge: unexpected argument type %{arg_class}, only expects hash arguments.') % { args_class: args.class }
26+
end
27+
28+
# We need to make a copy of the hash since it is frozen by puppet
29+
current = deep_copy(arg)
30+
31+
# Now we have to traverse our hash assigning our non-hash values
32+
# to the matching keys in our result while following our hash values
33+
# and repeating the process.
34+
overlay(result, current)
35+
end
36+
result
37+
end
38+
39+
def normalized?(hash, key)
40+
return true if hash.key?(key)
41+
return false unless key =~ %r{-|_}
42+
other_key = key.include?('-') ? key.tr('-', '_') : key.tr('_', '-')
43+
return false unless hash.key?(other_key)
44+
hash[key] = hash.delete(other_key)
45+
true
46+
end
47+
48+
def overlay(hash1, hash2)
49+
hash2.each do |key, value|
50+
if normalized?(hash1, key) && value.is_a?(Hash) && hash1[key].is_a?(Hash)
51+
overlay(hash1[key], value)
52+
else
53+
hash1[key] = value
54+
end
55+
end
56+
end
57+
58+
def deep_copy(inputhash)
59+
return inputhash unless inputhash.is_a? Hash
60+
hash = {}
61+
inputhash.each do |k, v|
62+
hash.store(k, deep_copy(v))
63+
end
64+
hash
65+
end
66+
end

lib/puppet/functions/mysql/dirname.rb

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# @summary
2+
# Returns the dirname of a path
3+
#
4+
Puppet::Functions.create_function(:'mysql::dirname') do
5+
# @param path
6+
# Path to find the dirname for.
7+
#
8+
# @return
9+
# Directory name of path.
10+
#
11+
dispatch :dirname do
12+
required_param 'Variant[String, Undef]', :path
13+
return_type 'String'
14+
end
15+
16+
def dirname(path)
17+
return '' if path.nil?
18+
File.dirname(path)
19+
end
20+
end
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
require 'digest/sha1'
2+
# @summary
3+
# Hash a string as mysql's "PASSWORD()" function would do it
4+
#
5+
Puppet::Functions.create_function(:'mysql::password') do
6+
# @param password
7+
# Plain text password.
8+
#
9+
# @return the mysql password hash from the clear text password.
10+
#
11+
dispatch :password do
12+
required_param 'String', :password
13+
return_type 'String'
14+
end
15+
16+
def password(password)
17+
return '' if password.empty?
18+
return password if password =~ %r{\*[A-F0-9]{40}$}
19+
'*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(password)).upcase
20+
end
21+
end
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# @summary
2+
# When given a hash this function strips out all blank entries.
3+
#
4+
Puppet::Functions.create_function(:'mysql::strip_hash') do
5+
# @param hash
6+
# Hash to be stripped
7+
#
8+
dispatch :strip_hash do
9+
required_param 'Hash', :hash
10+
return_type 'Hash'
11+
end
12+
13+
def strip_hash(hash)
14+
# Filter out all the top level blanks.
15+
hash.reject { |_k, v| v == '' }.each do |_k, v|
16+
v.reject! { |_ki, vi| vi == '' } if v.is_a?(Hash)
17+
end
18+
end
19+
end

manifests/backup/mysqlbackup.pp

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
mysql_user { "${backupuser}@localhost":
3131
ensure => $ensure,
32-
password_hash => mysql_password($backuppassword),
32+
password_hash => mysql::password($backuppassword),
3333
require => Class['mysql::server::root_password'],
3434
}
3535

@@ -92,7 +92,7 @@
9292
'password' => $backuppassword,
9393
}
9494
}
95-
$options = mysql_deepmerge($default_options, $mysql::server::override_options)
95+
$options = mysql::deepmerge($default_options, $mysql::server::override_options)
9696

9797
file { 'mysqlbackup-config-file':
9898
path => '/etc/mysql/conf.d/meb.cnf',

manifests/backup/mysqldump.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
mysql_user { "${backupuser}@localhost":
3535
ensure => $ensure,
36-
password_hash => mysql_password($backuppassword),
36+
password_hash => mysql::password($backuppassword),
3737
require => Class['mysql::server::root_password'],
3838
}
3939

manifests/backup/xtrabackup.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
if $backupuser and $backuppassword {
3737
mysql_user { "${backupuser}@localhost":
3838
ensure => $ensure,
39-
password_hash => mysql_password($backuppassword),
39+
password_hash => mysql::password($backuppassword),
4040
require => Class['mysql::server::root_password'],
4141
}
4242

manifests/db.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666

6767
$user_resource = {
6868
ensure => $ensure,
69-
password_hash => mysql_password($password),
69+
password_hash => mysql::password($password),
7070
}
7171
ensure_resource('mysql_user', "${user}@${host}", $user_resource)
7272

manifests/server.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
}
115115

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

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

manifests/server/binarylog.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
$logbin = pick($options['mysqld']['log-bin'], $options['mysqld']['log_bin'], false)
1212

1313
if $logbin {
14-
$logbindir = mysql_dirname($logbin)
14+
$logbindir = mysql::dirname($logbin)
1515

1616
#Stop puppet from managing directory if just a filename/prefix is specified
1717
if $logbindir != '.' {

manifests/server/config.pp

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
# 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,
2626
# managing this basedir is also required, to have it available before the package is installed.
27-
$includeparentdir = mysql_dirname($includedir)
27+
$includeparentdir = mysql::dirname($includedir)
2828
if $includeparentdir != '/' and $includeparentdir != '/etc' {
2929
file { $includeparentdir:
3030
ensure => directory,
@@ -43,9 +43,9 @@
4343

4444
# on mariadb systems, $includedir is not defined, but /etc/my.cnf.d has
4545
# to be managed to place the server.cnf there
46-
$configparentdir = mysql_dirname($mysql::server::config_file)
46+
$configparentdir = mysql::dirname($mysql::server::config_file)
4747
if $configparentdir != '/' and $configparentdir != '/etc' and $configparentdir
48-
!= $includedir and $configparentdir != mysql_dirname($includedir) {
48+
!= $includedir and $configparentdir != mysql::dirname($includedir) {
4949
file { $configparentdir:
5050
ensure => directory,
5151
mode => '0755',

manifests/server/monitor.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
mysql_user { "${mysql_monitor_username}@${mysql_monitor_hostname}":
2020
ensure => present,
21-
password_hash => mysql_password($mysql_monitor_password),
21+
password_hash => mysql::password($mysql_monitor_password),
2222
require => Class['mysql::server::service'],
2323
}
2424

manifests/server/root_password.pp

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
if $mysql::server::create_root_user == true and $mysql::server::root_password != 'UNSET' {
2727
mysql_user { 'root@localhost':
2828
ensure => present,
29-
password_hash => mysql_password($mysql::server::root_password),
29+
password_hash => mysql::password($mysql::server::root_password),
3030
require => Exec['remove install pass']
3131
}
3232
}
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#! /usr/bin/env ruby -S rspec # rubocop:disable Lint/ScriptPermission
2+
3+
require 'spec_helper'
4+
5+
describe 'mysql::deepmerge' do
6+
it 'exists' do
7+
is_expected.not_to eq(nil)
8+
end
9+
10+
it 'throws error with no arguments' do
11+
is_expected.to run.with_params.and_raise_error(Puppet::ParseError)
12+
end
13+
14+
it 'throws error with only one argument' do
15+
is_expected.to run.with_params('one' => 1).and_raise_error(Puppet::ParseError)
16+
end
17+
18+
it 'accepts empty strings as puppet undef' do
19+
is_expected.to run.with_params({}, '')
20+
end
21+
22+
# rubocop:disable RSpec/NamedSubject
23+
index_values = %w[one two three]
24+
expected_values_one = %w[1 2 2]
25+
it 'is able to mysql_deepmerge two hashes' do
26+
new_hash = subject.execute({ 'one' => '1', 'two' => '1' }, 'two' => '2', 'three' => '2')
27+
index_values.each_with_index do |index, expected|
28+
expect(new_hash[index]).to eq(expected_values_one[expected])
29+
end
30+
end
31+
32+
it 'mysql_deepmerges multiple hashes' do
33+
hash = subject.execute({ 'one' => 1 }, { 'one' => '2' }, 'one' => '3')
34+
expect(hash['one']).to eq('3')
35+
end
36+
37+
it 'accepts empty hashes' do
38+
is_expected.to run.with_params({}, {}, {}).and_return({})
39+
end
40+
41+
expected_values_two = [1, 2, 'four' => 4]
42+
it 'mysql_deepmerges subhashes' do
43+
hash = subject.execute({ 'one' => 1 }, 'two' => 2, 'three' => { 'four' => 4 })
44+
index_values.each_with_index do |index, expected|
45+
expect(hash[index]).to eq(expected_values_two[expected])
46+
end
47+
end
48+
49+
it 'appends to subhashes' do
50+
hash = subject.execute({ 'one' => { 'two' => 2 } }, 'one' => { 'three' => 3 })
51+
expect(hash['one']).to eq('two' => 2, 'three' => 3)
52+
end
53+
54+
expected_values_three = [1, 'dos', { 'four' => 4, 'five' => 5 }]
55+
it 'appends to subhashes 2' do
56+
hash = subject.execute({ 'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }, 'two' => 'dos', 'three' => { 'five' => 5 })
57+
index_values.each_with_index do |index, expected|
58+
expect(hash[index]).to eq(expected_values_three[expected])
59+
end
60+
end
61+
62+
index_values_two = %w[key1 key2]
63+
expected_values_four = [{ 'a' => 1, 'b' => 99 }, 'c' => 3]
64+
it 'appends to subhashes 3' do
65+
hash = subject.execute({ 'key1' => { 'a' => 1, 'b' => 2 }, 'key2' => { 'c' => 3 } }, 'key1' => { 'b' => 99 })
66+
index_values_two.each_with_index do |index, expected|
67+
expect(hash[index]).to eq(expected_values_four[expected])
68+
end
69+
end
70+
71+
it 'equates keys mod dash and underscore #value' do
72+
hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10)
73+
expect(hash['a_b_c']).to eq(10)
74+
end
75+
it 'equates keys mod dash and underscore #not' do
76+
hash = subject.execute({ 'a-b-c' => 1 }, 'a_b_c' => 10)
77+
expect(hash).not_to have_key('a-b-c')
78+
end
79+
80+
index_values_three = ['a_b_c', 'b-c-d']
81+
expected_values_five = [10, { 'e-f-g' => 3, 'c_d_e' => 12 }]
82+
index_values_error = ['a-b-c', 'b_c_d']
83+
index_values_three.each_with_index do |index, expected|
84+
it 'keeps style of the last when keys are equal mod dash and underscore #value' do
85+
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 })
86+
expect(hash[index]).to eq(expected_values_five[expected])
87+
end
88+
it 'keeps style of the last when keys are equal mod dash and underscore #not' do
89+
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 })
90+
expect(hash).not_to have_key(index_values_error[expected])
91+
end
92+
end
93+
# rubocop:enable RSpec/NamedSubject
94+
end

spec/functions/mysql_dirname_spec.rb

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require 'spec_helper'
2+
3+
describe 'mysql::dirname' do
4+
it 'exists' do
5+
is_expected.not_to eq(nil)
6+
end
7+
8+
it 'raises a ArgumentError if there is less than 1 arguments' do
9+
is_expected.to run.with_params.and_raise_error(ArgumentError)
10+
end
11+
12+
it 'raises a ArgumentError if there is more than 1 arguments' do
13+
is_expected.to run.with_params('foo', 'bar').and_raise_error(ArgumentError)
14+
end
15+
16+
it 'returns path of file' do
17+
is_expected.to run.with_params('spec/functions/mysql_dirname_spec.rb').and_return('spec/functions')
18+
end
19+
end

0 commit comments

Comments
 (0)