diff --git a/manifests/server/grant.pp b/manifests/server/grant.pp index 4382c6b..64be3ad 100644 --- a/manifests/server/grant.pp +++ b/manifests/server/grant.pp @@ -1,479 +1,485 @@ # @summary Define for granting permissions to roles. # # @param role Specifies the role or user whom you are granting access to. # @param db Specifies the database to which you are granting access. # @param privilege Specifies the privilege to grant. Valid options: 'ALL', 'ALL PRIVILEGES' or 'object_type' dependent string. # @param object_type Specifies the type of object to which you are granting privileges. Valid options: 'DATABASE', 'SCHEMA', 'SEQUENCE', 'ALL SEQUENCES IN SCHEMA', 'TABLE' or 'ALL TABLES IN SCHEMA'. # @param object_name Specifies name of object_type to which to grant access, can be either a string or a two element array. String: 'object_name' Array: ['schema_name', 'object_name'] # @param psql_db Specifies the database to execute the grant against. This should not ordinarily be changed from the default # @param psql_user Sets the OS user to run psql. # @param port Port to use when connecting. # @param onlyif_exists Create grant only if doesn't exist # @param connect_settings Specifies a hash of environment variables used when connecting to a remote server. # @param ensure Specifies whether to grant or revoke the privilege. Default is to grant the privilege. Valid values: 'present', 'absent'. # @param group Sets the OS group to run psql # @param psql_path Sets the path to psql command define postgresql::server::grant ( String $role, String $db, String $privilege = '', Pattern[#/(?i:^COLUMN$)/, /(?i:^ALL SEQUENCES IN SCHEMA$)/, /(?i:^ALL TABLES IN SCHEMA$)/, /(?i:^DATABASE$)/, #/(?i:^FOREIGN DATA WRAPPER$)/, #/(?i:^FOREIGN SERVER$)/, /(?i:^FUNCTION$)/, /(?i:^LANGUAGE$)/, #/(?i:^PROCEDURAL LANGUAGE$)/, /(?i:^TABLE$)/, #/(?i:^TABLESPACE$)/, /(?i:^SCHEMA$)/, /(?i:^SEQUENCE$)/ #/(?i:^VIEW$)/ ] $object_type = 'database', Optional[Variant[ Array[String,2,2], String[1]] ] $object_name = undef, Array[String[1],0] $object_arguments = [], String $psql_db = $postgresql::server::default_database, String $psql_user = $postgresql::server::user, Integer $port = $postgresql::server::port, Boolean $onlyif_exists = false, Hash $connect_settings = $postgresql::server::default_connect_settings, Enum['present', 'absent' ] $ensure = 'present', String $group = $postgresql::server::group, String $psql_path = $postgresql::server::psql_path, ) { case $ensure { default: { # default is 'present' - $sql_command = 'GRANT %s ON %s "%s%s" TO "%s"' - $sql_command_unquoted = 'GRANT %s ON %s %s%s TO "%s"' + $sql_command = 'GRANT %s ON %s "%s%s" TO %s' + $sql_command_unquoted = 'GRANT %s ON %s %s%s TO %s' $unless_is = true } 'absent': { - $sql_command = 'REVOKE %s ON %s "%s%s" FROM "%s"' - $sql_command_unquoted = 'REVOKE %s ON %s %s%s FROM "%s"' + $sql_command = 'REVOKE %s ON %s "%s%s" FROM %s' + $sql_command_unquoted = 'REVOKE %s ON %s %s%s FROM %s' $unless_is = false } } + # Quote the role if not PUBLIC + $_query_role = $role ? { + 'PUBLIC' => 'PUBLIC', + default => "\"${role}\"" + } + if ! $object_name { $_object_name = $db } else { $_object_name = $object_name } # # Port, order of precedence: $port parameter, $connect_settings[PGPORT], $postgresql::server::port # if $port != undef { $port_override = $port } elsif $connect_settings != undef and has_key( $connect_settings, 'PGPORT') { $port_override = undef } else { $port_override = $postgresql::server::port } ## Munge the input values $_object_type = upcase($object_type) $_privilege = upcase($privilege) # You can use ALL TABLES IN SCHEMA by passing schema_name to object_name # You can use ALL SEQUENCES IN SCHEMA by passing schema_name to object_name ## Validate that the object type's privilege is acceptable # TODO: this is a terrible hack; if they pass "ALL" as the desired privilege, # we need a way to test for it--and has_database_privilege does not # recognize 'ALL' as a valid privilege name. So we probably need to # hard-code a mapping between 'ALL' and the list of actual privileges that # it entails, and loop over them to check them. That sort of thing will # probably need to wait until we port this over to ruby, so, for now, we're # just going to assume that if they have "CREATE" privileges on a database, # then they have "ALL". (I told you that it was terrible!) case $_object_type { 'DATABASE': { $unless_privilege = $_privilege ? { 'ALL' => 'CREATE', 'ALL PRIVILEGES' => 'CREATE', Pattern[ /^$/, /^CONNECT$/, /^CREATE$/, /^TEMP$/, /^TEMPORARY$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_database_privilege' $on_db = $psql_db $onlyif_function = $ensure ? { default => undef, 'absent' => 'role_exists', } $arguments = '' $_enquote_object = true } 'SCHEMA': { $unless_privilege = $_privilege ? { 'ALL' => 'CREATE', 'ALL PRIVILEGES' => 'CREATE', Pattern[ /^$/, /^CREATE$/, /^USAGE$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_schema_privilege' $on_db = $db $onlyif_function = undef $arguments = '' $_enquote_object = true } 'SEQUENCE': { $unless_privilege = $_privilege ? { 'ALL' => 'USAGE', Pattern[ /^$/, /^ALL PRIVILEGES$/, /^SELECT$/, /^UPDATE$/, /^USAGE$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_sequence_privilege' $on_db = $db $onlyif_function = undef $arguments = '' $_enquote_object = true } 'ALL SEQUENCES IN SCHEMA': { case $_privilege { Pattern[ /^$/, /^ALL$/, /^ALL PRIVILEGES$/, /^SELECT$/, /^UPDATE$/, /^USAGE$/, ]: {} default: { fail('Illegal value for $privilege parameter') } } $unless_function = 'custom' $on_db = $db $onlyif_function = undef $arguments = '' $_enquote_object = true $schema = $object_name $custom_privilege = $_privilege ? { 'ALL' => 'USAGE', 'ALL PRIVILEGES' => 'USAGE', default => $_privilege, } # This checks if there is a difference between the sequences in the # specified schema and the sequences for which the role has the specified # privilege. It uses the EXCEPT clause which computes the set of rows # that are in the result of the first SELECT statement but not in the # result of the second one. It then counts the number of rows from this # operation. If this number is zero then the role has the specified # privilege for all sequences in the schema and the whole query returns a # single row, which satisfies the `unless` parameter of Postgresql_psql. # If this number is not zero then there is at least one sequence for which # the role does not have the specified privilege, making it necessary to # execute the GRANT statement. if $ensure == 'present' { $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema='${schema}' EXCEPT DISTINCT SELECT object_name as sequence_name FROM ( SELECT object_schema, object_name, grantee, CASE privs_split WHEN 'r' THEN 'SELECT' WHEN 'w' THEN 'UPDATE' WHEN 'U' THEN 'USAGE' END AS privilege_type FROM ( SELECT DISTINCT object_schema, object_name, regexp_replace((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1],'\"','','g') AS grantee, regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split FROM ( SELECT n.nspname as object_schema, c.relname as object_name, regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S' AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) ) P1 ) P2 ) P3 WHERE grantee='${role}' AND object_schema='${schema}' AND privilege_type='${custom_privilege}' )" } else { # ensure == absent $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT object_name as sequence_name FROM ( SELECT object_schema, object_name, grantee, CASE privs_split WHEN 'r' THEN 'SELECT' WHEN 'w' THEN 'UPDATE' WHEN 'U' THEN 'USAGE' END AS privilege_type FROM ( SELECT DISTINCT object_schema, object_name, regexp_replace((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[1],'\"','','g') AS grantee, regexp_split_to_table((regexp_split_to_array(regexp_replace(privs,E'/.*',''),'='))[2],E'\\s*') AS privs_split FROM ( SELECT n.nspname as object_schema, c.relname as object_name, regexp_split_to_table(array_to_string(c.relacl,','),',') AS privs FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind = 'S' AND n.nspname NOT IN ( 'pg_catalog', 'information_schema' ) ) P1 ) P2 ) P3 WHERE grantee='${role}' AND object_schema='${schema}' AND privilege_type='${custom_privilege}' )" } } 'TABLE': { $unless_privilege = $_privilege ? { 'ALL' => 'INSERT', Pattern[ /^$/, /^ALL$/, /^ALL PRIVILEGES$/, /^DELETE$/, /^INSERT$/, /^REFERENCES$/, /^SELECT$/, /^TRIGGER$/, /^TRUNCATE$/, /^UPDATE$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_table_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'table_exists', default => undef, } $arguments = '' $_enquote_object = true } 'ALL TABLES IN SCHEMA': { case $_privilege { Pattern[ /^$/, /^ALL$/, /^ALL PRIVILEGES$/, /^DELETE$/, /^INSERT$/, /^REFERENCES$/, /^SELECT$/, /^TRIGGER$/, /^TRUNCATE$/, /^UPDATE$/, ]: {} default: { fail('Illegal value for $privilege parameter') } } $unless_function = 'custom' $on_db = $db $onlyif_function = undef $arguments = '' $_enquote_object = true $schema = $object_name # Again there seems to be no easy way in plain SQL to check if ALL # PRIVILEGES are granted on a table. # There are currently 7 possible priviliges: # ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') # This list is consistant from Postgresql 8.0 # # There are 4 cases to cover, each with it's own distinct unless clause: # grant ALL # grant SELECT (or INSERT or DELETE ...) # revoke ALL # revoke SELECT (or INSERT or DELETE ...) if $ensure == 'present' { if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { # GRANT ALL $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT 1 FROM ( SELECT t.tablename,count(privilege_type) AS priv_count FROM pg_catalog.pg_tables AS t LEFT JOIN information_schema.role_table_grants AS g ON t.tablename = g.table_name AND g.grantee = '${role}' AND g.table_schema = '${schema}' WHERE t.schemaname = '${schema}' AND ( g.grantee = '${role}' AND privilege_type IN ('SELECT','UPDATE','INSERT','DELETE','TRIGGER','REFERENCES','TRUNCATE') OR privilege_type IS NULL ) GROUP BY t.tablename ) AS j WHERE j.priv_count < 7 )" } else { # GRANT $_privilege $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT 1 FROM pg_catalog.pg_tables AS t LEFT JOIN information_schema.role_table_grants AS g ON t.tablename = g.table_name AND g.grantee = '${role}' AND g.table_schema = '${schema}' AND g.privilege_type = '${_privilege}' WHERE t.schemaname = '${schema}' AND g.table_name IS NULL )" } } else { if $_privilege == 'ALL' or $_privilege == 'ALL PRIVILEGES' { # REVOKE ALL $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT table_name FROM information_schema.role_table_grants WHERE grantee = '${role}' AND table_schema ='${schema}' )" } else { # REVOKE $_privilege $custom_unless = "SELECT 1 WHERE NOT EXISTS ( SELECT table_name FROM information_schema.role_table_grants WHERE grantee = '${role}' AND table_schema ='${schema}' AND privilege_type = '${_privilege}' )" } } } 'LANGUAGE': { $unless_privilege = $_privilege ? { 'ALL' => 'USAGE', 'ALL PRIVILEGES' => 'USAGE', Pattern[ /^$/, /^CREATE$/, /^USAGE$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_language_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'language_exists', default => undef, } $arguments = '' $_enquote_object = false } 'FUNCTION': { $unless_privilege = $_privilege ? { 'ALL' => 'EXECUTE', 'ALL PRIVILEGES' => 'EXECUTE', Pattern[ /^$/, /^EXECUTE$/, ] => $_privilege, default => fail('Illegal value for $privilege parameter'), } $unless_function = 'has_function_privilege' $on_db = $db $onlyif_function = $onlyif_exists ? { true => 'function_exists', default => undef, } $_joined_args = join($object_arguments, ',') $arguments = "(${_joined_args})" $_enquote_object = false } default: { fail("Missing privilege validation for object type ${_object_type}") } } # This is used to give grant to "schemaname"."tablename" # If you need such grant, use: # postgresql::grant { 'table:foo': # role => 'joe', # ... # object_type => 'TABLE', # object_name => [$schema, $table], # } case $_object_name { Array: { $_togrant_object = $_enquote_object ? { false => join($_object_name, '.'), default => join($_object_name, '"."'), } # Never put double quotes into has_*_privilege function $_granted_object = join($_object_name, '.') } default: { $_granted_object = $_object_name $_togrant_object = $_object_name } } # Function like has_database_privilege() refer the PUBLIC pseudo role as 'public' # So we need to replace 'PUBLIC' by 'public'. $_unless = $unless_function ? { false => undef, 'custom' => $custom_unless, default => $role ? { 'PUBLIC' => "SELECT 1 WHERE ${unless_function}('public', '${_granted_object}${arguments}', '${unless_privilege}') = ${unless_is}", default => "SELECT 1 WHERE ${unless_function}('${role}', '${_granted_object}${arguments}', '${unless_privilege}') = ${unless_is}", } } $_onlyif = $onlyif_function ? { 'table_exists' => "SELECT true FROM pg_tables WHERE tablename = '${_togrant_object}'", 'language_exists' => "SELECT true from pg_language WHERE lanname = '${_togrant_object}'", 'role_exists' => "SELECT 1 FROM pg_roles WHERE rolname = '${role}' or '${role}' = 'PUBLIC'", 'function_exists' => "SELECT true FROM pg_proc WHERE (oid::regprocedure)::text = '${_togrant_object}${arguments}'", default => undef, } $grant_cmd = $_enquote_object ? { - false => sprintf($sql_command_unquoted, $_privilege, $_object_type, $_togrant_object, $arguments, $role), - default => sprintf($sql_command, $_privilege, $_object_type, $_togrant_object, $arguments, $role), + false => sprintf($sql_command_unquoted, $_privilege, $_object_type, $_togrant_object, $arguments, $_query_role), + default => sprintf($sql_command, $_privilege, $_object_type, $_togrant_object, $arguments, $_query_role), } postgresql_psql { "grant:${name}": command => $grant_cmd, db => $on_db, port => $port_override, connect_settings => $connect_settings, psql_user => $psql_user, psql_group => $group, psql_path => $psql_path, unless => $_unless, onlyif => $_onlyif, } if($role != undef and defined(Postgresql::Server::Role[$role])) { Postgresql::Server::Role[$role]->Postgresql_psql["grant:${name}"] } if($db != undef and defined(Postgresql::Server::Database[$db])) { Postgresql::Server::Database[$db]->Postgresql_psql["grant:${name}"] } } diff --git a/spec/unit/defines/server/grant_spec.rb b/spec/unit/defines/server/grant_spec.rb index 510e063..fa61e48 100644 --- a/spec/unit/defines/server/grant_spec.rb +++ b/spec/unit/defines/server/grant_spec.rb @@ -1,398 +1,398 @@ # frozen_string_literal: true require 'spec_helper' describe 'postgresql::server::grant', type: :define do let :facts do { os: { family: 'Debian', name: 'Debian', release: { 'full' => '8.0', 'major' => '8' }, }, kernel: 'Linux', id: 'root', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end context 'plain' do let :params do { db: 'test', role: 'test', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } end context 'sequence' do let :params do { db: 'test', role: 'test', privilege: 'usage', object_type: 'sequence', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m) end end context 'SeQuEnCe case insensitive object_type match' do let :params do { db: 'test', role: 'test', privilege: 'usage', object_type: 'SeQuEnCe', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m) end end context 'all sequences' do let :params do { db: 'test', role: 'test', privilege: 'usage', object_type: 'all sequences in schema', object_name: 'public', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT USAGE ON ALL SEQUENCES IN SCHEMA "public" TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE NOT EXISTS \(\s*SELECT sequence_name\s* FROM information_schema\.sequences\s* WHERE sequence_schema='public'\s* EXCEPT DISTINCT\s* SELECT object_name as sequence_name\s* FROM .* WHERE .*grantee='test'\s* AND object_schema='public'\s* AND privilege_type='USAGE'\s*\)}m) # rubocop:disable Layout/LineLength end end context 'with specific db connection settings - default port' do let :params do { db: 'test', role: 'test', connect_settings: { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1').with_port(5432) } end context 'with specific db connection settings - including port' do let :params do { db: 'test', role: 'test', connect_settings: { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234') } end context 'with specific db connection settings - port overriden by explicit parameter' do let :params do { db: 'test', role: 'test', connect_settings: { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234' }, port: 5678, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql_psql('grant:test').with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234').with_port('5678') } end context 'with specific schema name' do let :params do { db: 'test', role: 'test', privilege: 'all', object_name: ['myschema', 'mytable'], object_type: 'table', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE has_table_privilege\('test',\s*'myschema.mytable', 'INSERT'\)}m) end end context 'with a role defined' do let :params do { db: 'test', role: 'test', privilege: 'all', object_name: ['myschema', 'mytable'], object_type: 'table', } end let :pre_condition do <<-EOS class {'postgresql::server':} postgresql::server::role { 'test': } EOS end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql__server__role('test') } it do is_expected.to contain_postgresql_psql('grant:test') \ .that_requires(['Class[postgresql::server::service]', 'Postgresql::Server::Role[test]']) end end context 'with a role defined to PUBLIC' do let :params do { db: 'test', role: 'PUBLIC', privilege: 'all', object_name: ['myschema', 'mytable'], object_type: 'table', } end let :pre_condition do <<-EOS class {'postgresql::server':} postgresql::server::role { 'test': } EOS end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it { is_expected.to contain_postgresql__server__role('test') } it do is_expected.to contain_postgresql_psql('grant:test') - .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* "PUBLIC"}m) + .with_command(%r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* PUBLIC}m) .with_unless(%r{SELECT 1 WHERE has_table_privilege\('public',\s*'myschema.mytable', 'INSERT'\)}m) end end context 'function' do let :params do { db: 'test', role: 'test', privilege: 'execute', object_name: 'test', object_arguments: ['text', 'boolean'], object_type: 'function', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT EXECUTE ON FUNCTION test\(text,boolean\) TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE has_function_privilege\('test',\s* 'test\(text,boolean\)', 'EXECUTE'\)}m) end end context 'function with schema' do let :params do { db: 'test', role: 'test', privilege: 'execute', object_name: ['myschema', 'test'], object_arguments: ['text', 'boolean'], object_type: 'function', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_postgresql__server__grant('test') } it do is_expected.to contain_postgresql_psql('grant:test') .with_command(%r{GRANT EXECUTE ON FUNCTION myschema.test\(text,boolean\) TO\s* "test"}m) .with_unless(%r{SELECT 1 WHERE has_function_privilege\('test',\s* 'myschema.test\(text,boolean\)', 'EXECUTE'\)}m) end end context 'standalone not managing server' do let :params do { db: 'test', role: 'test', privilege: 'execute', object_name: ['myschema', 'test'], object_arguments: ['text', 'boolean'], object_type: 'function', group: 'postgresql', psql_path: '/usr/bin', psql_user: 'postgres', psql_db: 'db', port: 1542, connect_settings: {}, } end it { is_expected.to compile.with_all_deps } it { is_expected.not_to contain_class('postgresql::server') } end context 'invalid object_type' do let :params do { db: 'test', role: 'test', privilege: 'usage', object_type: 'invalid', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.and_raise_error(%r{parameter 'object_type' expects a match for Pattern}) } end context 'invalid object_name - wrong type' do let :params do { db: 'test', role: 'test', privilege: 'all', object_name: 1, object_type: 'table', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' expects a value of type (Array|Undef, Array,) or String, got Integer}) } end context 'invalid object_name - insufficent array elements' do let :params do { db: 'test', role: 'test', privilege: 'all', object_name: ['oops'], object_type: 'table', } end let :pre_condition do "class {'postgresql::server':}" end if Puppet::Util::Package.versioncmp(Puppet.version, '5.2.0') >= 0 it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 1 expects size to be 2, got 1}) } else it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 0 expects size to be 2, got 1}) } end end context 'invalid object_name - too many array elements' do let :params do { db: 'test', role: 'test', privilege: 'all', object_name: ['myschema', 'mytable', 'oops'], object_type: 'table', } end let :pre_condition do "class {'postgresql::server':}" end if Puppet::Util::Package.versioncmp(Puppet.version, '5.2.0') >= 0 it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 1 expects size to be 2, got 3}) } else it { is_expected.to compile.and_raise_error(%r{parameter 'object_name' variant 0 expects size to be 2, got 3}) } end end end