diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 7f7252c..3332730 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -1,129 +1,101 @@ require 'puppet' require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' require 'beaker/puppet_install_helper' require 'beaker/module_install_helper' require 'beaker/task_helper' run_puppet_install_helper install_ca_certs unless pe_install? UNSUPPORTED_PLATFORMS = %w[AIX windows Solaris Suse].freeze -# monkey patch to get around apt/forge issue (PUP-8008) -module Beaker::ModuleInstallHelper - include Beaker::DSL - - def module_dependencies_from_metadata - metadata = module_metadata - return [] unless metadata.key?('dependencies') - - dependencies = [] - - # get it outta here! - metadata['dependencies'].delete_if { |d| d['name'] == 'puppetlabs/apt' } - - metadata['dependencies'].each do |d| - tmp = { module_name: d['name'].sub('/', '-') } - - if d.key?('version_requirement') - tmp[:version] = module_version_from_requirement(tmp[:module_name], - d['version_requirement']) - end - dependencies.push(tmp) - end - - dependencies - end -end - install_bolt_on(hosts) unless pe_install? install_module_on(hosts) install_module_dependencies_on(hosts) -install_module_from_forge_on(hosts, 'puppetlabs/apt', '< 4.2.0') DEFAULT_PASSWORD = if default[:hypervisor] == 'vagrant' 'vagrant' elsif default[:hypervisor] == 'vcloud' 'Qu@lity!' end class String # Provide ability to remove indentation from strings, for the purpose of # left justifying heredoc blocks. def unindent gsub(%r{^#{scan(%r{^\s*}).min_by { |l| l.length }}}, '') end end def shellescape(str) str = str.to_s # An empty argument will be skipped, so return empty quotes. return "''" if str.empty? str = str.dup # Treat multibyte characters as is. It is caller's responsibility # to encode the string in the right encoding for the shell # environment. str.gsub!(%r{([^A-Za-z0-9_\-.,:\/@\n])}, '\\\\\\1') # A LF cannot be escaped with a backslash because a backslash + LF # combo is regarded as line continuation and simply ignored. str.gsub!(%r{\n}, "'\n'") str end def psql(psql_cmd, user = 'postgres', exit_codes = [0, 1], &block) psql = "psql #{psql_cmd}" shell("su #{shellescape(user)} -c #{shellescape(psql)}", acceptable_exit_codes: exit_codes, &block) end RSpec.configure do |c| # Readable test descriptions c.formatter = :documentation # Configure all nodes in nodeset c.before :suite do run_puppet_access_login(user: 'admin') if pe_install? && puppet_version =~ %r{(5\.\d\.\d)} # Set up selinux if appropriate. if fact('osfamily') == 'RedHat' && fact('selinux') == 'true' pp = <<-EOS if $::osfamily == 'RedHat' and $::selinux == 'true' { $semanage_package = $::operatingsystemmajrelease ? { '5' => 'policycoreutils', default => 'policycoreutils-python', } package { $semanage_package: ensure => installed } exec { 'set_postgres': command => 'semanage port -a -t postgresql_port_t -p tcp 5433', path => '/bin:/usr/bin/:/sbin:/usr/sbin', subscribe => Package[$semanage_package], } } EOS apply_manifest_on(agents, pp, catch_failures: false) end # net-tools required for netstat utility being used by be_listening if fact('osfamily') == 'RedHat' && fact('operatingsystemmajrelease') == '7' pp = <<-EOS package { 'net-tools': ensure => installed } EOS apply_manifest_on(agents, pp, catch_failures: false) end hosts.each do |host| on host, 'chmod 755 /root' next unless fact_on(host, 'osfamily') == 'Debian' on host, "echo \"en_US ISO-8859-1\nen_NG.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\n\" > /etc/locale.gen" on host, '/usr/sbin/locale-gen' on host, '/usr/sbin/update-locale' end end end diff --git a/spec/unit/defines/server/grant_spec.rb b/spec/unit/defines/server/grant_spec.rb index 6b38458..a41b1f0 100644 --- a/spec/unit/defines/server/grant_spec.rb +++ b/spec/unit/defines/server/grant_spec.rb @@ -1,264 +1,295 @@ require 'spec_helper' describe 'postgresql::server::grant', type: :define do let :facts do { osfamily: 'Debian', operatingsystem: 'Debian', operatingsystemrelease: '6.0', kernel: 'Linux', concat_basedir: tmpfilename('contrib'), 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 { - is_expected.to contain_postgresql_psql('grant:test').with( - 'command' => %r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m, - 'unless' => %r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m, - ) - } + 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 { - is_expected.to contain_postgresql_psql('grant:test').with( - 'command' => %r{GRANT USAGE ON SEQUENCE "test" TO\s* "test"}m, - 'unless' => %r{SELECT 1 WHERE has_sequence_privilege\('test',\s* 'test', 'USAGE'\)}m, - ) - } + 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 { - is_expected.to contain_postgresql_psql('grant:test').with( - 'command' => %r{GRANT USAGE ON ALL SEQUENCES IN SCHEMA "public" TO\s* "test"}m, - '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 Metrics/LineLength - ) - } + 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 Metrics/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: %w[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 { - is_expected.to contain_postgresql_psql('grant:test').with( - 'command' => %r{GRANT ALL ON TABLE "myschema"."mytable" TO\s* "test"}m, - 'unless' => %r{SELECT 1 WHERE has_table_privilege\('test',\s*'myschema.mytable', 'INSERT'\)}m, - ) - } + 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: %w[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('Postgresql::Server::Role[test]') + end 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: %w[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 diff --git a/spec/unit/defines/server/reassign_owned_by_spec.rb b/spec/unit/defines/server/reassign_owned_by_spec.rb index 1c8bd9f..c71dfa8 100644 --- a/spec/unit/defines/server/reassign_owned_by_spec.rb +++ b/spec/unit/defines/server/reassign_owned_by_spec.rb @@ -1,43 +1,43 @@ require 'spec_helper' describe 'postgresql::server::reassign_owned_by', type: :define do let :facts do { osfamily: 'Debian', operatingsystem: 'Debian', operatingsystemrelease: '6.0', kernel: 'Linux', concat_basedir: tmpfilename('reassign_owned_by'), id: 'root', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end let :params do { db: 'test', old_role: 'test_old_role', new_role: 'test_new_role', } end let :pre_condition do <<-MANIFEST class {'postgresql::server':} postgresql::server::role{ ['test_old_role','test_new_role']: } MANIFEST end it { is_expected.to contain_postgresql__server__reassign_owned_by('test') } it { is_expected.to contain_postgresql_psql('reassign_owned_by:test:REASSIGN OWNED BY "test_old_role" TO "test_new_role"') - .with('command' => 'REASSIGN OWNED BY "test_old_role" TO "test_new_role"', - 'onlyif' => %r{SELECT tablename FROM pg_catalog.pg_tables WHERE\s*schemaname NOT IN \('pg_catalog', 'information_schema'\) AND\s*tableowner = 'test_old_role'.*}m) + .with_command('REASSIGN OWNED BY "test_old_role" TO "test_new_role"') + .with_onlyif(%r{SELECT tablename FROM pg_catalog.pg_tables WHERE\s*schemaname NOT IN \('pg_catalog', 'information_schema'\) AND\s*tableowner = 'test_old_role'.*}m) .that_requires('Class[postgresql::server]') } end diff --git a/spec/unit/defines/server/role_spec.rb b/spec/unit/defines/server/role_spec.rb index 1cd2ca9..ba8ff87 100644 --- a/spec/unit/defines/server/role_spec.rb +++ b/spec/unit/defines/server/role_spec.rb @@ -1,143 +1,144 @@ require 'spec_helper' describe 'postgresql::server::role', type: :define do let :facts do { osfamily: 'Debian', operatingsystem: 'Debian', operatingsystemrelease: '6.0', kernel: 'Linux', concat_basedir: tmpfilename('contrib'), id: 'root', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', } end let :title do 'test' end let :params do { password_hash: 'new-pa$s', } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'has create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') .with('command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => 'NEWPGPASSWD=new-pa$s', 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'port' => '5432') end it 'has alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') .with('command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => 'NEWPGPASSWD=new-pa$s', 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'port' => '5432') end context 'with specific db connection settings - default port' do let :params do { password_hash: 'new-pa$s', connect_settings: { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'has create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') - .with('command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => 'NEWPGPASSWD=new-pa$s', - 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'port' => '5432', - 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', - 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }) + .with_command("CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1") + .with_environment('NEWPGPASSWD=new-pa$s') + .with_unless("SELECT 1 FROM pg_roles WHERE rolname = 'test'") + .with_port(5432) + .with_connect_settings('PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass') end it 'has alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') .with('command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => 'NEWPGPASSWD=new-pa$s', 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'port' => '5432', 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }) end end context 'with specific db connection settings - including port' do let :params do { password_hash: 'new-pa$s', connect_settings: { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }, } end let :pre_condition do "class {'postgresql::server':}" end it { is_expected.to contain_postgresql__server__role('test') } it 'has create role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****') .with('command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", 'environment' => 'NEWPGPASSWD=new-pa$s', 'unless' => "SELECT 1 FROM pg_roles WHERE rolname = 'test'", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }) end it 'has alter role for "test" user with password as ****' do is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') .with('command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", 'environment' => 'NEWPGPASSWD=new-pa$s', 'unless' => "SELECT 1 FROM pg_shadow WHERE usename = 'test' AND passwd = 'md5b6f7fcbbabb4befde4588a26c1cfd2fa'", 'connect_settings' => { 'PGHOST' => 'postgres-db-server', 'DBVERSION' => '9.1', 'PGPORT' => '1234', 'PGUSER' => 'login-user', 'PGPASSWORD' => 'login-pass' }) end end context 'with update_password set to false' do let :params do { password_hash: 'new-pa$s', update_password: false, } end let :pre_condition do "class {'postgresql::server':}" end it 'does not have alter role for "test" user with password as **** if update_password is false' do is_expected.not_to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****') end end context 'with ensure set to absent' do let :params do { ensure: 'absent', } end let :pre_condition do "class {'postgresql::server':}" end it 'has drop role for "test" user if ensure absent' do is_expected.to contain_postgresql_psql('DROP ROLE "test"') end end end