diff --git a/REFERENCE.md b/REFERENCE.md index 41f820d532..5544a5f329 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -61,14 +61,18 @@ _Private Classes_ **Functions** +_Public Functions_ + * [`postgresql::default`](#postgresqldefault): This function pull default values from the `params` class or `globals` class if the value is not present in `params`. -* [`postgresql::postgresql_acls_to_resources_hash`](#postgresqlpostgresql_acls_to_resources_hash): This internal function translates the ipv(4|6)acls format into a resource * [`postgresql::postgresql_escape`](#postgresqlpostgresql_escape): This function safely escapes a string using a consistent random tag * [`postgresql::postgresql_password`](#postgresqlpostgresql_password): This function returns the postgresql password hash from the clear text username / password -* [`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 * [`postgresql_escape`](#postgresql_escape): This function safely escapes a string using a consistent random tag * [`postgresql_password`](#postgresql_password): This function returns the postgresql password hash from the clear text username / password +_Private Functions_ + +* `postgresql::postgresql_acls_to_resources_hash`: This internal function translates the ipv(4|6)acls format into a resource suitable for create_resources. + **Tasks** * [`sql`](#sql): Allows you to execute arbitary SQL @@ -842,7 +846,7 @@ Default value: $postgresql::params::ip_mask_allow_all_users ##### `ipv4acls` -Data type: `Any` +Data type: `Array[String[1]]` Lists strings for access control for connection method, users, databases, IPv4 addresses; @@ -850,7 +854,7 @@ Default value: $postgresql::params::ipv4acls ##### `ipv6acls` -Data type: `Any` +Data type: `Array[String[1]]` Lists strings for access control for connection method, users, databases, IPv6 addresses. @@ -1097,6 +1101,14 @@ Sets PostgreSQL version Default value: `undef` +##### `extra_systemd_config` + +Data type: `Any` + +Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string + +Default value: $postgresql::params::extra_systemd_config + ##### `manage_selinux` Data type: `Boolean` @@ -1667,6 +1679,22 @@ Specifies whether to grant or revoke the privilege. Default is to grant the priv Default value: 'present' +##### `group` + +Data type: `String` + +Sets the OS group to run psql + +Default value: $postgresql::server::group + +##### `psql_path` + +Data type: `String` + +Sets the path to psql command + +Default value: $postgresql::server::psql_path + ##### `object_arguments` Data type: `Array[String[1],0]` @@ -2181,6 +2209,38 @@ Specify whether to create or drop the role. Specifying 'present' creates the rol Default value: 'present' +##### `psql_user` + +Data type: `Any` + +Sets the OS user to run psql + +Default value: $postgresql::server::user + +##### `psql_group` + +Data type: `Any` + +Sets the OS group to run psql + +Default value: $postgresql::server::group + +##### `psql_path` + +Data type: `Any` + +Sets path to psql command + +Default value: $postgresql::server::psql_path + +##### `module_workdir` + +Data type: `Any` + +Specifies working directory under which the psql command should be executed. May need to specify if '/tmp' is on volume mounted with noexec option. + +Default value: $postgresql::server::module_workdir + ### postgresql::server::schema Create a new schema. @@ -2723,69 +2783,6 @@ Data type: `String` -### postgresql::postgresql_acls_to_resources_hash - -Type: Ruby 4.x API - -This is an autogenerated function, ported from the original legacy version. -It /should work/ as is, but will not have all the benefits of the modern -function API. You should see the function docs to learn how to add function -signatures for type safety and to document this function using puppet-strings. - -https://puppet.com/docs/puppet/latest/custom_functions_ruby.html - ----- original file header ---- -postgresql_acls_to_resources_hash.rb ----- original file header ---- - - suitable for create_resources. It is not intended to be used outside of the - postgresql internal classes/defined resources. - - @return This function accepts an array of strings that are pg_hba.conf rules. It - will return a hash that can be fed into create_resources to create multiple - individual pg_hba_rule resources. - - The second parameter is an identifier that will be included in the namevar - to provide uniqueness. It must be a string. - - The third parameter is an order offset, so you can start the order at an - arbitrary starting point. - -#### `postgresql::postgresql_acls_to_resources_hash(Any *$args)` - -This is an autogenerated function, ported from the original legacy version. -It /should work/ as is, but will not have all the benefits of the modern -function API. You should see the function docs to learn how to add function -signatures for type safety and to document this function using puppet-strings. - -https://puppet.com/docs/puppet/latest/custom_functions_ruby.html - ----- original file header ---- -postgresql_acls_to_resources_hash.rb ----- original file header ---- - - suitable for create_resources. It is not intended to be used outside of the - postgresql internal classes/defined resources. - - @return This function accepts an array of strings that are pg_hba.conf rules. It - will return a hash that can be fed into create_resources to create multiple - individual pg_hba_rule resources. - - The second parameter is an identifier that will be included in the namevar - to provide uniqueness. It must be a string. - - The third parameter is an order offset, so you can start the order at an - arbitrary starting point. - -Returns: `Data type` Describe what the function returns here - -##### `*args` - -Data type: `Any` - -The original array of arguments. Port this to individually managed params -to get the full benefit of the modern function API. - ### postgresql::postgresql_escape Type: Ruby 4.x API @@ -2836,40 +2833,6 @@ Data type: `Any` The original array of arguments. Port this to individually managed params to get the full benefit of the modern function API. -### postgresql_acls_to_resources_hash - -Type: Ruby 3.x API - -This internal function translates the ipv(4|6)acls format into a resource -suitable for create_resources. It is not intended to be used outside of the -postgresql internal classes/defined resources. - -will return a hash that can be fed into create_resources to create multiple -individual pg_hba_rule resources. - -The second parameter is an identifier that will be included in the namevar -to provide uniqueness. It must be a string. - -The third parameter is an order offset, so you can start the order at an -arbitrary starting point. - -#### `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 outside of the -postgresql internal classes/defined resources. - -will return a hash that can be fed into create_resources to create multiple -individual pg_hba_rule resources. - -The second parameter is an identifier that will be included in the namevar -to provide uniqueness. It must be a string. - -The third parameter is an order offset, so you can start the order at an -arbitrary starting point. - -Returns: `Any` This function accepts an array of strings that are pg_hba.conf rules. It - ### postgresql_escape Type: Ruby 3.x API diff --git a/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb b/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb index 3a6f15e309..9625454f86 100644 --- a/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb +++ b/lib/puppet/functions/postgresql/postgresql_acls_to_resources_hash.rb @@ -1,64 +1,22 @@ -# This is an autogenerated function, ported from the original legacy version. -# It /should work/ as is, but will not have all the benefits of the modern -# function API. You should see the function docs to learn how to add function -# signatures for type safety and to document this function using puppet-strings. -# -# https://puppet.com/docs/puppet/latest/custom_functions_ruby.html -# -# ---- original file header ---- -# postgresql_acls_to_resources_hash.rb -# ---- original file header ---- -# -# @summary -# This internal function translates the ipv(4|6)acls format into a resource -# suitable for create_resources. It is not intended to be used outside of the -# postgresql internal classes/defined resources. -# -# @return This function accepts an array of strings that are pg_hba.conf rules. It -# will return a hash that can be fed into create_resources to create multiple -# individual pg_hba_rule resources. -# -# The second parameter is an identifier that will be included in the namevar -# to provide uniqueness. It must be a string. -# -# The third parameter is an order offset, so you can start the order at an -# arbitrary starting point. -# -# +# @summary This internal function translates the ipv(4|6)acls format into a resource suitable for create_resources. +# @api private Puppet::Functions.create_function(:'postgresql::postgresql_acls_to_resources_hash') do - # @param args - # The original array of arguments. Port this to individually managed params - # to get the full benefit of the modern function API. - # - # @return [Data type] - # Describe what the function returns here + # @param acls + # An array of strings that are pg_hba.conf rules. + # @param id + # An identifier that will be included in the namevar to provide uniqueness. + # @param offset + # An order offset, so you can start the order at an arbitrary starting point. # + # @return [Hash] + # A hash that can be fed into create_resources to create multiple individual pg_hba_rule resources. dispatch :default_impl do - # Call the method named 'default_impl' when this is matched - # Port this to match individual params for better type safety - repeated_param 'Any', :args + param 'Array[String]', :acls + param 'String[1]', :id + param 'Integer[0]', :offset end - def default_impl(*args) - func_name = 'postgresql_acls_to_resources_hash()' - - if args.size != 3 - raise(Puppet::ParseError, "#{func_name}: Wrong number of arguments " \ - "given (#{args.size} for 3)") - end - - acls = args[0] - raise(Puppet::ParseError, "#{func_name}: first argument must be an array") \ - unless acls.instance_of? Array - - id = args[1] - raise(Puppet::ParseError, "#{func_name}: second argument must be a string") \ - unless id.instance_of? String - - offset = args[2].to_i - raise(Puppet::ParseError, "#{func_name}: third argument must be a number") \ - unless offset.is_a? Integer - + def default_impl(acls, id, offset) resources = {} acls.each do |acl| index = acls.index(acl) @@ -66,15 +24,15 @@ def default_impl(*args) parts = acl.split unless parts.length >= 4 - raise(Puppet::ParseError, "#{func_name}: acl line #{index} does not " \ + raise(Puppet::ParseError, "postgresql::postgresql_acls_to_resources_hash(): acl line #{index} does not " \ 'have enough parts') end resource = { - 'type' => parts[0], + 'type' => parts[0], 'database' => parts[1], - 'user' => parts[2], - 'order' => format('%03d', offset + index), # rubocop:disable Style/FormatString + 'user' => parts[2], + 'order' => '%03d' % (offset + index), } if parts[0] == 'local' resource['auth_method'] = parts[3] diff --git a/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb b/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb deleted file mode 100644 index 86a2d6005a..0000000000 --- a/lib/puppet/parser/functions/postgresql_acls_to_resources_hash.rb +++ /dev/null @@ -1,75 +0,0 @@ -# postgresql_acls_to_resources_hash.rb -module Puppet::Parser::Functions - newfunction(:postgresql_acls_to_resources_hash, type: :rvalue, doc: <<-EOS - This internal function translates the ipv(4|6)acls format into a resource - suitable for create_resources. It is not intended to be used outside of the - postgresql internal classes/defined resources. - - @return This function accepts an array of strings that are pg_hba.conf rules. It - will return a hash that can be fed into create_resources to create multiple - individual pg_hba_rule resources. - - The second parameter is an identifier that will be included in the namevar - to provide uniqueness. It must be a string. - - The third parameter is an order offset, so you can start the order at an - arbitrary starting point. - EOS - ) do |args| - func_name = 'postgresql_acls_to_resources_hash()' - - if args.size != 3 - raise(Puppet::ParseError, "#{func_name}: Wrong number of arguments " \ - "given (#{args.size} for 3)") - end - - acls = args[0] - raise(Puppet::ParseError, "#{func_name}: first argument must be an array") \ - unless acls.instance_of? Array - - id = args[1] - raise(Puppet::ParseError, "#{func_name}: second argument must be a string") \ - unless id.instance_of? String - - offset = args[2].to_i - raise(Puppet::ParseError, "#{func_name}: third argument must be a number") \ - unless offset.is_a? Integer - - resources = {} - acls.each do |acl| - index = acls.index(acl) - - parts = acl.split - - unless parts.length >= 4 - raise(Puppet::ParseError, "#{func_name}: acl line #{index} does not " \ - 'have enough parts') - end - - resource = { - 'type' => parts[0], - 'database' => parts[1], - 'user' => parts[2], - 'order' => format('%03d', offset + index), # rubocop:disable Style/FormatString - } - if parts[0] == 'local' - resource['auth_method'] = parts[3] - if parts.length > 4 - resource['auth_option'] = parts.last(parts.length - 4).join(' ') - end - elsif parts[4] =~ %r{^\d} - resource['address'] = parts[3] + ' ' + parts[4] - resource['auth_method'] = parts[5] - - resource['auth_option'] = parts.last(parts.length - 6).join(' ') if parts.length > 6 - else - resource['address'] = parts[3] - resource['auth_method'] = parts[4] - - resource['auth_option'] = parts.last(parts.length - 5).join(' ') if parts.length > 5 - end - resources["postgresql class generated rule #{id} #{index}"] = resource - end - resources - end -end diff --git a/manifests/server.pp b/manifests/server.pp index 5b65a2f224..b28345362c 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -100,8 +100,8 @@ $port = $postgresql::params::port, $ip_mask_deny_postgres_user = $postgresql::params::ip_mask_deny_postgres_user, $ip_mask_allow_all_users = $postgresql::params::ip_mask_allow_all_users, - $ipv4acls = $postgresql::params::ipv4acls, - $ipv6acls = $postgresql::params::ipv6acls, + Array[String[1]] $ipv4acls = $postgresql::params::ipv4acls, + Array[String[1]] $ipv6acls = $postgresql::params::ipv6acls, $initdb_path = $postgresql::params::initdb_path, $createdb_path = $postgresql::params::createdb_path, diff --git a/manifests/server/config.pp b/manifests/server/config.pp index 6af92c07a7..93bc9b9396 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -88,18 +88,16 @@ } } - # ipv4acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv4acl_resources = postgresql_acls_to_resources_hash($ipv4acls, - 'ipv4acls', 10) - create_resources('postgresql::server::pg_hba_rule', $ipv4acl_resources) - - - # ipv6acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv6acl_resources = postgresql_acls_to_resources_hash($ipv6acls, - 'ipv6acls', 102) - create_resources('postgresql::server::pg_hba_rule', $ipv6acl_resources) + # $ipv4acls and $ipv6acls are arrays of rule strings + # They are converted into hashes we can iterate over to create postgresql::server::pg_hba_rule resources. + ( + postgresql::postgresql_acls_to_resources_hash($ipv4acls, 'ipv4acls', 10) + + postgresql::postgresql_acls_to_resources_hash($ipv6acls, 'ipv6acls', 102) + ).each | String $key, Hash $attrs| { + postgresql::server::pg_hba_rule { $key: + * => $attrs, + } + } } if $listen_addresses { diff --git a/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb b/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb index 2df689df18..21a1ee1842 100644 --- a/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb +++ b/spec/functions/postgresql_postgresql_acls_to_resources_hash_spec.rb @@ -1,40 +1,148 @@ require 'spec_helper' describe 'postgresql::postgresql_acls_to_resources_hash' do - # without knowing details about the implementation, this is the only test - # case that we can autogenerate. You should add more examples below! it { is_expected.not_to eq(nil) } + context 'individual transform tests' do + it do + input = 'local all postgres ident' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'postgres', + 'auth_method' => 'ident', + 'order' => '100', + }, + } + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end - ################################# - # Below are some example test cases. You may uncomment and modify them to match - # your needs. Notice that they all expect the base error class of `StandardError`. - # This is because the autogenerated function uses an untyped array for parameters - # and relies on your implementation to do the validation. As you convert your - # function to proper dispatches and typed signatures, you should change the - # expected error of the argument validation examples to `ArgumentError`. - # - # Other error types you might encounter include - # - # * StandardError - # * ArgumentError - # * Puppet::ParseError - # - # Read more about writing function unit tests at https://rspec-puppet.com/documentation/functions/ - # - # it 'raises an error if called with no argument' do - # is_expected.to run.with_params.and_raise_error(StandardError) - # end - # - # it 'raises an error if there is more than 1 arguments' do - # is_expected.to run.with_params({ 'foo' => 1 }, 'bar' => 2).and_raise_error(StandardError) - # end - # - # it 'raises an error if argument is not the proper type' do - # is_expected.to run.with_params('foo').and_raise_error(StandardError) - # end - # - # it 'returns the proper output' do - # is_expected.to run.with_params(123).and_return('the expected output') - # end - ################################# + it do + input = 'local all root ident' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'root', + 'auth_method' => 'ident', + 'order' => '100', + }, + } + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input_array = ['local all all ident'] + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'local', + 'database' => 'all', + 'user' => 'all', + 'auth_method' => 'ident', + 'order' => '100', + }, + } + is_expected.to run.with_params(input_array, 'test', 100).and_return(result) + end + + it do + input = 'host all all 127.0.0.1/32 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '127.0.0.1/32', + 'auth_method' => 'md5', + 'order' => '100', + }, + } + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 0.0.0.0/0 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '0.0.0.0/0', + 'auth_method' => 'md5', + 'order' => '100', + }, + } + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all ::1/128 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '::1/128', + 'auth_method' => 'md5', + 'order' => '100', + }, + } + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 1.1.1.1 255.255.255.0 md5' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '1.1.1.1 255.255.255.0', + 'auth_method' => 'md5', + 'order' => '100', + }, + } + + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + + it do + input = 'host all all 1.1.1.1 255.255.255.0 ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"' + result = { + 'postgresql class generated rule test 0' => { + 'type' => 'host', + 'database' => 'all', + 'user' => 'all', + 'address' => '1.1.1.1 255.255.255.0', + 'auth_method' => 'ldap', + 'auth_option' => 'ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"', + 'order' => '100', + }, + } + + is_expected.to run.with_params([input], 'test', 100).and_return(result) + end + end + + context 'error catching tests' do + it do + is_expected.to run.with_params(['test'], 'test').and_raise_error(%r{expects 3 arguments, got 2}) + end + + it do + is_expected.to run.with_params('test', 'test', 100).and_raise_error(%r{parameter 'acls' expects an Array value, got String}) + end + + it do + is_expected.to run.with_params(['test'], 100, 'test').and_raise_error(%r{parameter 'id' expects a String value, got Integer}) + end + + it do + is_expected.to run.with_params(['test'], 'test', 1).and_raise_error(%r{does not have enough parts}) + end + end + + it 'returns an empty hash when input is empty array' do + is_expected.to run.with_params([], 'test', 100).and_return({}) + end end diff --git a/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb b/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb deleted file mode 100644 index b38b244918..0000000000 --- a/spec/unit/functions/postgresql_acls_to_resources_hash_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'spec_helper' - -describe 'postgresql_acls_to_resources_hash', type: :puppet_function do - context 'individual transform tests' do - it do - input = 'local all postgres ident' - result = { 'postgresql class generated rule test 0' => { 'type' => 'local', 'database' => 'all', 'user' => 'postgres', - 'auth_method' => 'ident', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'local all root ident' - result = { 'postgresql class generated rule test 0' => { 'type' => 'local', 'database' => 'all', 'user' => 'root', - 'auth_method' => 'ident', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input_array = ['local all all ident'] - result = { 'postgresql class generated rule test 0' => { 'type' => 'local', 'database' => 'all', 'user' => 'all', - 'auth_method' => 'ident', 'order' => '100' } } - - is_expected.to run.with_params(input_array, 'test', 100).and_return(result) - end - - it do - input = 'host all all 127.0.0.1/32 md5' - result = { 'postgresql class generated rule test 0' => { 'type' => 'host', 'database' => 'all', 'user' => 'all', 'address' => '127.0.0.1/32', - 'auth_method' => 'md5', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 0.0.0.0/0 md5' - result = { 'postgresql class generated rule test 0' => { 'type' => 'host', 'database' => 'all', 'user' => 'all', 'address' => '0.0.0.0/0', - 'auth_method' => 'md5', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all ::1/128 md5' - result = { 'postgresql class generated rule test 0' => { 'type' => 'host', 'database' => 'all', 'user' => 'all', 'address' => '::1/128', - 'auth_method' => 'md5', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 1.1.1.1 255.255.255.0 md5' - result = { 'postgresql class generated rule test 0' => { 'type' => 'host', 'database' => 'all', 'user' => 'all', 'address' => '1.1.1.1 255.255.255.0', - 'auth_method' => 'md5', 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - - it do - input = 'host all all 1.1.1.1 255.255.255.0 ldap ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"' - result = { 'postgresql class generated rule test 0' => { 'type' => 'host', 'database' => 'all', 'user' => 'all', 'address' => '1.1.1.1 255.255.255.0', - 'auth_method' => 'ldap', 'auth_option' => 'ldapserver=ldap.example.net ldapprefix="cn=" ldapsuffix=", dc=example, dc=net"', - 'order' => '100' } } - - is_expected.to run.with_params([input], 'test', 100).and_return(result) - end - end - - context 'error catching tests' do - it do - is_expected.to run.with_params(['test'], 'test').and_raise_error(%r{Wrong number of arguments}) - end - - it do - is_expected.to run.with_params('test', 'test', 100).and_raise_error(%r{first argument must be an array}) - end - - it do - is_expected.to run.with_params(['test'], 100, 'test').and_raise_error(%r{second argument must be a string}) - end - - it do - is_expected.to run.with_params(['test'], 'test', 1).and_raise_error(%r{does not have enough parts}) - end - end - - it 'returns an empty hash when input is empty array' do - is_expected.to run.with_params([], 'test', 100).and_return({}) - end -end