Skip to content

Commit e7d5ef0

Browse files
committed
Finish conversion of postgresql_escape function
In puppetlabs#1129 the 3 functions from this module were ported to the modern function API and namespaced. None of the boilerplate was fixed up, tests weren't updated, documentation wasn't updated etc. This commit finishes the work for the `postgresql_escape` function. * Remove old API puppet/parser/functions version. * Create a replacement non-namespaced, (but deprecated), new API shim that calls the namespaced version. This function is *probably* not being used outside of this module, but it doesn't hurt to get the old version around for now. * Replace argument validation in the function code with data-type based validation for the individual function parameters. * Refactor function for increased readability. * Test both shim and namespaced version of the function. * Update `postgresql::server` to use namespaced version. * Update REFERENCE.md
1 parent 84df848 commit e7d5ef0

File tree

9 files changed

+133
-155
lines changed

9 files changed

+133
-155
lines changed

REFERENCE.md

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ _Private Classes_
6363

6464
* [`postgresql::default`](#postgresqldefault): This function pull default values from the `params` class or `globals` class if the value is not present in `params`.
6565
* [`postgresql::postgresql_acls_to_resources_hash`](#postgresqlpostgresql_acls_to_resources_hash): This internal function translates the ipv(4|6)acls format into a resource
66-
* [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape): This function safely escapes a string using a consistent random tag
66+
* [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape): This function escapes a string by performing `Dollar Quoting` using a randomly generated tag if required.
6767
* [`postgresql::postgresql_password`](#postgresqlpostgresql_password): This function returns the postgresql password hash from the clear text username / password
6868
* [`postgresql_acls_to_resources_hash`](#postgresql_acls_to_resources_hash): This internal function translates the ipv(4|6)acls format into a resource suitable for create_resources. It is not intended to be used outsid
69-
* [`postgresql_escape`](#postgresql_escape): This function safely escapes a string using a consistent random tag
69+
* [`postgresql_escape`](#postgresql_escape): DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.
7070
* [`postgresql_password`](#postgresql_password): This function returns the postgresql password hash from the clear text username / password
7171

7272
**Tasks**
@@ -1097,6 +1097,14 @@ Sets PostgreSQL version
10971097

10981098
Default value: `undef`
10991099

1100+
##### `extra_systemd_config`
1101+
1102+
Data type: `Any`
1103+
1104+
Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string
1105+
1106+
Default value: $postgresql::params::extra_systemd_config
1107+
11001108
##### `manage_selinux`
11011109

11021110
Data type: `Boolean`
@@ -1667,6 +1675,22 @@ Specifies whether to grant or revoke the privilege. Default is to grant the priv
16671675

16681676
Default value: 'present'
16691677

1678+
##### `group`
1679+
1680+
Data type: `String`
1681+
1682+
Sets the OS group to run psql
1683+
1684+
Default value: $postgresql::server::group
1685+
1686+
##### `psql_path`
1687+
1688+
Data type: `String`
1689+
1690+
Sets the path to psql command
1691+
1692+
Default value: $postgresql::server::psql_path
1693+
16701694
##### `object_arguments`
16711695

16721696
Data type: `Array[String[1],0]`
@@ -2181,6 +2205,38 @@ Specify whether to create or drop the role. Specifying 'present' creates the rol
21812205

21822206
Default value: 'present'
21832207

2208+
##### `psql_user`
2209+
2210+
Data type: `Any`
2211+
2212+
Sets the OS user to run psql
2213+
2214+
Default value: $postgresql::server::user
2215+
2216+
##### `psql_group`
2217+
2218+
Data type: `Any`
2219+
2220+
Sets the OS group to run psql
2221+
2222+
Default value: $postgresql::server::group
2223+
2224+
##### `psql_path`
2225+
2226+
Data type: `Any`
2227+
2228+
Sets path to psql command
2229+
2230+
Default value: $postgresql::server::psql_path
2231+
2232+
##### `module_workdir`
2233+
2234+
Data type: `Any`
2235+
2236+
Specifies working directory under which the psql command should be executed. May need to specify if '/tmp' is on volume mounted with noexec option.
2237+
2238+
Default value: $postgresql::server::module_workdir
2239+
21842240
### postgresql::server::schema
21852241

21862242
Create a new schema.
@@ -2790,26 +2846,19 @@ to get the full benefit of the modern function API.
27902846

27912847
Type: Ruby 4.x API
27922848

2793-
postgresql_escape.rb
2794-
---- original file header ----
2795-
2796-
@return Safely escapes a string using $$ using a random tag which should be consistent
2849+
This function escapes a string by performing `Dollar Quoting` using a randomly generated tag if required.
27972850

2798-
#### `postgresql::postgresql_escape(Any *$args)`
2851+
#### `postgresql::postgresql_escape(String[1] $input_string)`
27992852

2800-
postgresql_escape.rb
2801-
---- original file header ----
2853+
The postgresql::postgresql_escape function.
28022854

2803-
@return Safely escapes a string using $$ using a random tag which should be consistent
2855+
Returns: `String` A `Dollar Quoted` string
28042856

2805-
Returns: `Data type` Describe what the function returns here
2857+
##### `input_string`
28062858

2807-
##### `*args`
2808-
2809-
Data type: `Any`
2859+
Data type: `String[1]`
28102860

2811-
The original array of arguments. Port this to individually managed params
2812-
to get the full benefit of the modern function API.
2861+
The unescaped string you want to escape using `dollar quoting`
28132862

28142863
### postgresql::postgresql_password
28152864

@@ -2872,15 +2921,21 @@ Returns: `Any` This function accepts an array of strings that are pg_hba.conf ru
28722921

28732922
### postgresql_escape
28742923

2875-
Type: Ruby 3.x API
2924+
Type: Ruby 4.x API
28762925

2877-
This function safely escapes a string using a consistent random tag
2926+
DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.
28782927

2879-
#### `postgresql_escape()`
2928+
#### `postgresql_escape(Any *$args)`
2929+
2930+
The postgresql_escape function.
2931+
2932+
Returns: `Any`
2933+
2934+
##### `*args`
2935+
2936+
Data type: `Any`
28802937

2881-
This function safely escapes a string using a consistent random tag
28822938

2883-
Returns: `Any` Safely escapes a string using $$ using a random tag which should be consistent
28842939

28852940
### postgresql_password
28862941

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,31 @@
1-
# This is an autogenerated function, ported from the original legacy version.
2-
# It /should work/ as is, but will not have all the benefits of the modern
3-
# function API. You should see the function docs to learn how to add function
4-
# signatures for type safety and to document this function using puppet-strings.
5-
#
6-
# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html
7-
#
8-
# ---- original file header ----
91
require 'digest/md5'
102

11-
# postgresql_escape.rb
12-
# ---- original file header ----
13-
#
14-
# @summary
15-
# This function safely escapes a string using a consistent random tag
16-
# @return Safely escapes a string using $$ using a random tag which should be consistent
17-
#
18-
#
3+
# @summary This function escapes a string by performing `Dollar Quoting` using a randomly generated tag if required.
4+
# @see https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING
195
Puppet::Functions.create_function(:'postgresql::postgresql_escape') do
20-
# @param args
21-
# The original array of arguments. Port this to individually managed params
22-
# to get the full benefit of the modern function API.
23-
#
24-
# @return [Data type]
25-
# Describe what the function returns here
6+
# @param input_string
7+
# The unescaped string you want to escape using `dollar quoting`
268
#
9+
# @return [String]
10+
# A `Dollar Quoted` string
2711
dispatch :default_impl do
28-
# Call the method named 'default_impl' when this is matched
29-
# Port this to match individual params for better type safety
30-
repeated_param 'Any', :args
12+
param 'String[1]', :input_string
3113
end
3214

33-
def default_impl(*args)
34-
if args.size != 1
35-
raise(Puppet::ParseError, 'postgresql_escape(): Wrong number of arguments ' \
36-
"given (#{args.size} for 1)")
15+
def default_impl(input_string)
16+
# Where allowed, just return the original string wrapped in `$$`
17+
return "$$#{input_string}$$" unless tag_needed?(input_string)
18+
19+
# Keep generating possible values for tag until we find one that doesn't appear in the input string
20+
tag = Digest::MD5.hexdigest(input_string)[0..5].gsub(%r{\d}, '')
21+
until input_string !~ %r{#{tag}}
22+
tag = Digest::MD5.hexdigest(tag)[0..5].gsub(%r{\d}, '')
3723
end
3824

39-
password = args[0]
25+
"$#{tag}$#{input_string}$#{tag}$"
26+
end
4027

41-
if password !~ %r{\$\$} && password[-1] != '$'
42-
retval = "$$#{password}$$"
43-
else
44-
escape = Digest::MD5.hexdigest(password)[0..5].gsub(%r{\d}, '')
45-
until password !~ %r{#{escape}}
46-
escape = Digest::MD5.hexdigest(escape)[0..5].gsub(%r{\d}, '')
47-
end
48-
retval = "$#{escape}$#{password}$#{escape}$"
49-
end
50-
retval
28+
def tag_needed?(input_string)
29+
input_string =~ %r{\$\$} || input_string.end_with?('$')
5130
end
5231
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# @summary DEPRECATED. Use the namespaced function [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape) instead.
2+
Puppet::Functions.create_function(:postgresql_escape) do
3+
dispatch :deprecation_gen do
4+
repeated_param 'Any', :args
5+
end
6+
def deprecation_gen(*args)
7+
call_function('deprecation', 'postgresql_escape', 'This method is deprecated, please use postgresql::postgresql_escape instead.')
8+
call_function('postgresql::postgresql_escape', *args)
9+
end
10+
end

lib/puppet/parser/functions/postgresql_escape.rb

Lines changed: 0 additions & 29 deletions
This file was deleted.

manifests/server/passwd.pp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
default => ''
1616
}
1717

18-
if ($postgres_password != undef) {
18+
if $postgres_password {
1919
# NOTE: this password-setting logic relies on the pg_hba.conf being
2020
# configured to allow the postgres system user to connect via psql
2121
# without specifying a password ('ident' or 'trust' security). This is
2222
# the default for pg_hba.conf.
23-
$escaped = postgresql_escape($postgres_password)
23+
$escaped = postgresql::postgresql_escape($postgres_password)
2424
exec { 'set_postgres_postgrespw':
2525
# This command works w/no password because we run it as postgres system
2626
# user
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require 'spec_helper'
2+
3+
describe 'postgresql_escape' do
4+
it_behaves_like 'postgresql_escape function'
5+
end
Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,5 @@
11
require 'spec_helper'
22

33
describe 'postgresql::postgresql_escape' do
4-
# without knowing details about the implementation, this is the only test
5-
# case that we can autogenerate. You should add more examples below!
6-
it { is_expected.not_to eq(nil) }
7-
8-
#################################
9-
# Below are some example test cases. You may uncomment and modify them to match
10-
# your needs. Notice that they all expect the base error class of `StandardError`.
11-
# This is because the autogenerated function uses an untyped array for parameters
12-
# and relies on your implementation to do the validation. As you convert your
13-
# function to proper dispatches and typed signatures, you should change the
14-
# expected error of the argument validation examples to `ArgumentError`.
15-
#
16-
# Other error types you might encounter include
17-
#
18-
# * StandardError
19-
# * ArgumentError
20-
# * Puppet::ParseError
21-
#
22-
# Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/
23-
#
24-
# it 'raises an error if called with no argument' do
25-
# is_expected.to run.with_params.and_raise_error(StandardError)
26-
# end
27-
#
28-
# it 'raises an error if there is more than 1 arguments' do
29-
# is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError)
30-
# end
31-
#
32-
# it 'raises an error if argument is not the proper type' do
33-
# is_expected.to run.with_params('foo').and_raise_error(StandardError)
34-
# end
35-
#
36-
# it 'returns the proper output' do
37-
# is_expected.to run.with_params(123).and_return('the expected output')
38-
# end
39-
#################################
4+
it_behaves_like 'postgresql_escape function'
405
end

spec/spec_helper_local.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,23 @@
4141
def param(type, title, param)
4242
param_value(catalogue, type, title, param)
4343
end
44+
45+
shared_examples 'postgresql_escape function' do
46+
it { is_expected.not_to eq(nil) }
47+
it {
48+
is_expected.to run.with_params('foo')
49+
.and_return('$$foo$$')
50+
}
51+
it {
52+
is_expected.to run.with_params('fo$$o')
53+
.and_return('$ed$fo$$o$ed$')
54+
}
55+
it {
56+
is_expected.to run.with_params('foo$')
57+
.and_return('$a$foo$$a$')
58+
}
59+
it 'raises an error if there is more than 1 argument' do
60+
is_expected.to run.with_params(['foo'], ['foo'])
61+
.and_raise_error(StandardError)
62+
end
63+
end

spec/unit/functions/postgresql_escape_spec.rb

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)