Add actual postgresl module from puppetlabs
[mirror/dsa-puppet.git] / 3rdparty / modules / postgresql / spec / system / install_spec.rb
1 require 'spec_helper_system'
2
3 describe 'install:' do
4   after :all do
5     # Cleanup after tests have ran
6     puppet_apply("class { 'postgresql::server': ensure => absent }") do |r|
7       r.exit_code.should_not == 1
8     end
9   end
10
11   it 'test postgresql::server' do
12     pp = <<-EOS
13       class { 'postgresql::server': }
14     EOS
15
16     puppet_apply(pp) do |r|
17       r.exit_code.should_not == 1
18     end
19
20     puppet_apply(pp) do |r|
21       r.exit_code.should be_zero
22     end
23   end
24
25   describe 'postgresql::db' do
26     it 'should idempotently create a db that we can connect to' do
27       begin
28         pp = <<-EOS
29           $db = 'postgresql_test_db'
30           include postgresql::server
31
32           postgresql::db { $db:
33             user        => $db,
34             password    => postgresql_password($db, $db),
35           }
36         EOS
37
38         puppet_apply(pp) do |r|
39           r.exit_code.should_not == 1
40         end
41
42         puppet_apply(pp) do |r|
43           r.exit_code.should == 0
44         end
45
46         psql('--command="select datname from pg_database" postgresql_test_db') do |r|
47           r.stdout.should =~ /postgresql_test_db/
48           r.stderr.should be_empty
49           r.exit_code.should == 0
50         end
51       ensure
52         psql('--command="drop database postgresql_test_db" postgres')
53       end
54     end
55
56     it 'should take a locale parameter' do
57       pending('no support for locale parameter with centos 5', :if => (node.facts['osfamily'] == 'RedHat' and node.facts['lsbmajdistrelease'] == '5'))
58       begin
59         pp = <<-EOS
60           class { 'postgresql::server': }
61           if($::operatingsystem == 'Debian') {
62             # Need to make sure the correct locale is installed first
63             file { '/etc/locale.gen':
64               content => "en_US ISO-8859-1\nen_NG UTF-8\n",
65             }~>
66             exec { '/usr/sbin/locale-gen':
67               logoutput => true,
68               refreshonly => true,
69             }
70           }
71           postgresql::db { 'test1':
72             user     => 'test1',
73             password => postgresql_password('test1', 'test1'),
74             charset => 'UTF8',
75             locale => 'en_NG',
76           }
77         EOS
78
79         puppet_apply(pp) do |r|
80           r.exit_code.should_not == 1
81         end
82
83         puppet_apply(pp) do |r|
84           r.exit_code.should == 0
85         end
86
87         psql('-c "show lc_ctype" test1') do |r|
88           r.stdout.should =~ /en_NG/
89         end
90
91         psql('-c "show lc_collate" test1') do |r|
92           r.stdout.should =~ /en_NG/
93         end
94       ensure
95         psql('--command="drop database test1" postgres')
96       end
97     end
98
99     it 'should take an istemplate parameter' do
100       begin
101         pp = <<-EOS
102           $db = 'template2'
103           include postgresql::server
104
105           postgresql::db { $db:
106             user        => $db,
107             password    => postgresql_password($db, $db),
108             istemplate  => true,
109           }
110         EOS
111
112         puppet_apply(pp) do |r|
113           r.exit_code.should_not == 1
114         end
115
116         puppet_apply(pp) do |r|
117           r.exit_code.should == 0
118         end
119
120         psql('--command="select datname from pg_database" template2') do |r|
121           r.stdout.should =~ /template2/
122           r.stderr.should be_empty
123           r.exit_code.should == 0
124         end
125       ensure
126         psql('--command="drop database template2" postgres') do |r|
127           r.stdout.should be_empty
128           r.stderr.should =~ /cannot drop a template database/
129           r.exit_code.should_not == 0
130         end
131       end
132     end
133
134     it 'should update istemplate parameter' do
135       begin
136         pp = <<-EOS
137           $db = 'template2'
138           include postgresql::server
139
140           postgresql::db { $db:
141             user        => $db,
142             password    => postgresql_password($db, $db),
143             istemplate  => false,
144           }
145         EOS
146
147         puppet_apply(pp) do |r|
148           r.exit_code.should_not == 1
149         end
150
151         puppet_apply(pp) do |r|
152           r.exit_code.should == 0
153         end
154
155         psql('--command="select datname from pg_database" template2') do |r|
156           r.stdout.should =~ /template2/
157           r.stderr.should be_empty
158           r.exit_code.should == 0
159         end
160       ensure
161         psql('--command="drop database template2" postgres') do |r|
162           r.exit_code.should == 0
163         end
164       end
165     end
166   end
167
168   describe 'postgresql::psql' do
169     it 'should work but emit a deprecation warning' do
170       pp = <<-EOS
171         include postgresql::server
172
173         postgresql::psql { 'foobar':
174           db       => 'postgres',
175           user     => 'postgres',
176           command  => 'select * from pg_database limit 1',
177           unless   => 'select 1 where 1=1',
178           require  => Class['postgresql::server'],
179         }
180       EOS
181
182       puppet_apply(pp) do |r|
183         r.exit_code.should_not == 1
184         r.stdout.should =~ /postgresql::psql is deprecated/
185       end
186
187       puppet_apply(pp) do |r|
188         r.exit_code.should == 2
189         r.stdout.should =~ /postgresql::psql is deprecated/
190       end
191     end
192   end
193
194   describe 'postgresql_psql' do
195     it 'should run some SQL when the unless query returns no rows' do
196       pp = <<-EOS
197         include postgresql::server
198
199         postgresql_psql { 'foobar':
200           db          => 'postgres',
201           psql_user   => 'postgres',
202           command     => 'select 1',
203           unless      => 'select 1 where 1=2',
204           require     => Class['postgresql::server'],
205         }
206       EOS
207
208       puppet_apply(pp) do |r|
209         r.exit_code.should_not == 1
210       end
211
212       puppet_apply(pp) do |r|
213         r.exit_code.should == 2
214       end
215     end
216
217     it 'should not run SQL when the unless query returns rows' do
218       pp = <<-EOS
219         include postgresql::server
220
221         postgresql_psql { 'foobar':
222           db          => 'postgres',
223           psql_user   => 'postgres',
224           command     => 'select * from pg_database limit 1',
225           unless      => 'select 1 where 1=1',
226           require     => Class['postgresql::server'],
227         }
228       EOS
229
230       puppet_apply(pp) do |r|
231         r.exit_code.should_not == 1
232       end
233
234       puppet_apply(pp) do |r|
235         r.exit_code.should be_zero
236       end
237     end
238   end
239
240   describe 'postgresql::user' do
241     it 'should idempotently create a user who can log in' do
242       pp = <<-EOS
243         $user = "postgresql_test_user"
244         $password = "postgresql_test_password"
245
246         include postgresql::server
247
248         # Since we are not testing pg_hba or any of that, make a local user for ident auth
249         user { $user:
250           ensure => present,
251         }
252
253         postgresql::database_user { $user:
254           password_hash => postgresql_password($user, $password),
255           require  => [ Class['postgresql::server'],
256                         User[$user] ],
257         }
258       EOS
259
260       puppet_apply(pp) do |r|
261         r.exit_code.should_not == 1
262       end
263
264       puppet_apply(pp) do |r|
265         r.exit_code.should be_zero
266       end
267
268       # Check that the user can log in
269       psql('--command="select datname from pg_database" postgres', 'postgresql_test_user') do |r|
270         r.stdout.should =~ /template1/
271         r.stderr.should be_empty
272         r.exit_code.should == 0
273       end
274     end
275
276     it 'should idempotently alter a user who can log in' do
277       pp = <<-EOS
278         $user = "postgresql_test_user"
279         $password = "postgresql_test_password2"
280
281         include postgresql::server
282
283         # Since we are not testing pg_hba or any of that, make a local user for ident auth
284         user { $user:
285           ensure => present,
286         }
287
288         postgresql::database_user { $user:
289           password_hash => postgresql_password($user, $password),
290           require  => [ Class['postgresql::server'],
291                         User[$user] ],
292         }
293       EOS
294
295       puppet_apply(pp) do |r|
296         r.exit_code.should_not == 1
297       end
298
299       puppet_apply(pp) do |r|
300         r.exit_code.should be_zero
301       end
302
303       # Check that the user can log in
304       psql('--command="select datname from pg_database" postgres', 'postgresql_test_user') do |r|
305         r.stdout.should =~ /template1/
306         r.stderr.should be_empty
307         r.exit_code.should == 0
308       end
309     end
310   end
311
312   describe 'postgresql::database_grant' do
313     it 'should grant access so a user can create in a database' do
314       begin
315         pp = <<-EOS
316           $db = 'postgres'
317           $user = 'psql_grant_tester'
318           $password = 'psql_grant_pw'
319
320           include postgresql::server
321
322           # Since we are not testing pg_hba or any of that, make a local user for ident auth
323           user { $user:
324             ensure => present,
325           }
326
327           postgresql::database_user { $user:
328             password_hash => postgresql_password($user, $password),
329             require       => [
330               Class['postgresql::server'],
331               User[$user],
332             ],
333           }
334
335           postgresql::database { $db:
336             require => Class['postgresql::server'],
337           }
338
339           postgresql::database_grant { 'grant create test':
340             privilege => 'CREATE',
341             db        => $db,
342             role      => $user,
343             require   => [
344               Postgresql::Database[$db],
345               Postgresql::Database_user[$user],
346             ],
347           }
348         EOS
349
350         puppet_apply(pp) do |r|
351           r.exit_code.should_not == 1
352         end
353
354         puppet_apply(pp) do |r|
355           r.exit_code.should be_zero
356         end
357
358         # Check that the user can create a table in the database
359         psql('--command="create table foo (foo int)" postgres', 'psql_grant_tester') do |r|
360           r.stdout.should =~ /CREATE TABLE/
361           r.stderr.should be_empty
362           r.exit_code.should == 0
363         end
364       ensure
365         psql('--command="drop table foo" postgres', 'psql_grant_tester')
366       end
367     end
368   end
369
370   describe 'postgresql::table_grant' do
371     it 'should grant access so a user can insert in a table' do
372       begin
373         pp = <<-EOS
374           $db = 'table_grant'
375           $user = 'psql_table_tester'
376           $password = 'psql_table_pw'
377
378           include postgresql::server
379
380           # Since we are not testing pg_hba or any of that, make a local user for ident auth
381           user { $user:
382             ensure => present,
383           }
384
385           postgresql::database_user { $user:
386             password_hash => postgresql_password($user, $password),
387             require       => [
388               Class['postgresql::server'],
389               User[$user],
390             ],
391           }
392
393           postgresql::database { $db:
394             require => Class['postgresql::server'],
395           }
396
397           postgresql_psql { 'Create testing table':
398             command => 'CREATE TABLE "test_table" (field integer NOT NULL)',
399             db      => $db,
400             unless  => "SELECT * FROM pg_tables WHERE tablename = 'test_table'",
401             require => Postgresql::Database[$db],
402           }
403
404           postgresql::table_grant { 'grant insert test':
405             privilege => 'INSERT',
406             table     => 'test_table',
407             db        => $db,
408             role      => $user,
409             require   => [
410               Postgresql::Database[$db],
411               Postgresql::Database_user[$user],
412               Postgresql_psql['Create testing table'],
413             ],
414           }
415         EOS
416
417         puppet_apply(pp) do |r|
418           r.exit_code.should_not == 1
419         end
420
421         puppet_apply(pp) do |r|
422           r.exit_code.should be_zero
423         end
424
425         ## Check that the user can create a table in the database
426         #psql('--command="create table foo (foo int)" postgres', 'psql_grant_tester') do |r|
427         #  r.stdout.should =~ /CREATE TABLE/
428         #  r.stderr.should be_empty
429         #  r.exit_code.should == 0
430         #end
431       ensure
432         #psql('--command="drop table foo" postgres', 'psql_grant_tester')
433       end
434     end
435   end
436
437   describe 'postgresql::validate_db_connections' do
438     it 'should run puppet with no changes declared if database connectivity works' do
439       pp = <<-EOS
440         $db = 'foo'
441         include postgresql::server
442
443         postgresql::db { $db:
444           user        => $db,
445           password    => postgresql_password($db, $db),
446         }
447       EOS
448
449       puppet_apply(pp) do |r|
450         r.exit_code.should_not == 1
451       end
452
453       puppet_apply(pp) do |r|
454         r.exit_code.should be_zero
455       end
456
457       pp = <<-EOS
458         postgresql::validate_db_connection { 'foo':
459           database_host => 'localhost',
460           database_name => 'foo',
461           database_username => 'foo',
462           database_password => 'foo',
463         }
464       EOS
465
466       puppet_apply(pp) do |r|
467         r.exit_code.should be_zero
468       end
469     end
470
471     it 'should fail catalogue if database connectivity fails' do
472       pp = <<-EOS
473         postgresql::validate_db_connection { 'foobarbaz':
474           database_host => 'localhost',
475           database_name => 'foobarbaz',
476           database_username => 'foobarbaz',
477           database_password => 'foobarbaz',
478         }
479       EOS
480
481       puppet_apply(pp) do |r|
482         r.exit_code.should == 4
483       end
484     end
485   end
486
487   describe 'postgresql::tablespace' do
488     it 'should idempotently create tablespaces and databases that are using them' do
489       pp = <<-EOS
490         include postgresql::server
491
492         file { '/tmp/pg_tablespaces':
493           ensure  => 'directory',
494           owner   => 'postgres',
495           group   => 'postgres',
496           mode    => '0700',
497         }~>
498         # This works around rubies that lack Selinux support, I'm looking at you RHEL5
499         exec { "chcon -u system_u -r object_r -t postgresql_db_t /tmp/pg_tablespaces":
500           refreshonly => true,
501           path        => "/bin:/usr/bin",
502           onlyif      => "which chcon",
503           before      => File["/tmp/pg_tablespaces/space1", "/tmp/pg_tablespaces/space2"]
504         }
505
506         postgresql::tablespace{ 'tablespace1':
507           location => '/tmp/pg_tablespaces/space1',
508           require => [Class['postgresql::server'], File['/tmp/pg_tablespaces']],
509         }
510         postgresql::database{ 'tablespacedb1':
511           charset => 'utf8',
512           tablespace => 'tablespace1',
513           require => Postgresql::Tablespace['tablespace1'],
514         }
515         postgresql::db{ 'tablespacedb2':
516           user => 'dbuser2',
517           password => postgresql_password('dbuser2', 'dbuser2'),
518           tablespace => 'tablespace1',
519           require => Postgresql::Tablespace['tablespace1'],
520         }
521
522         postgresql::database_user{ 'spcuser':
523           password_hash => postgresql_password('spcuser', 'spcuser'),
524           require       => Class['postgresql::server'],
525         }
526         postgresql::tablespace{ 'tablespace2':
527           location => '/tmp/pg_tablespaces/space2',
528           owner => 'spcuser',
529           require => [Postgresql::Database_user['spcuser'], File['/tmp/pg_tablespaces']],
530         }
531         postgresql::database{ 'tablespacedb3':
532           charset => 'utf8',
533           tablespace => 'tablespace2',
534           require => Postgresql::Tablespace['tablespace2'],
535         }
536       EOS
537
538       puppet_apply(pp) do |r|
539         r.exit_code.should_not == 1
540       end
541
542       puppet_apply(pp) do |r|
543         r.exit_code.should == 0
544       end
545
546       # Check that databases use correct tablespaces
547       psql('--command="select ts.spcname from pg_database db, pg_tablespace ts where db.dattablespace = ts.oid and db.datname = \'"\'tablespacedb1\'"\'"') do |r|
548         r.stdout.should =~ /tablespace1/
549         r.stderr.should be_empty
550         r.exit_code.should == 0
551       end
552
553       psql('--command="select ts.spcname from pg_database db, pg_tablespace ts where db.dattablespace = ts.oid and db.datname = \'"\'tablespacedb3\'"\'"') do |r|
554         r.stdout.should =~ /tablespace2/
555         r.stderr.should be_empty
556         r.exit_code.should == 0
557       end
558     end
559   end
560
561   describe 'postgresql::pg_hba_rule' do
562     it 'should create a ruleset in pg_hba.conf' do
563       pp = <<-EOS
564         include postgresql::server
565         postgresql::pg_hba_rule { "allow application network to access app database":
566           type => "host",
567           database => "app",
568           user => "app",
569           address => "200.1.2.0/24",
570           auth_method => md5,
571         }
572       EOS
573
574       puppet_apply(pp) do |r|
575         r.exit_code.should_not == 1
576       end
577
578       puppet_apply(pp) do |r|
579         r.exit_code.should be_zero
580       end
581
582       shell("grep '200.1.2.0/24' /etc/postgresql/*/*/pg_hba.conf || grep '200.1.2.0/24' /var/lib/pgsql/data/pg_hba.conf") do |r|
583         r.exit_code.should be_zero
584       end
585     end
586
587     it 'should create a ruleset in pg_hba.conf that denies db access to db test1' do
588       pp = <<-EOS
589         include postgresql::server
590         postgresql::db { "test1":
591           user => "test1",
592           password => postgresql_password('test1', 'test1'),
593           grant => "all",
594         }
595         postgresql::pg_hba_rule { "allow anyone to have access to db test1":
596           type => "local",
597           database => "test1",
598           user => "test1",
599           auth_method => reject,
600           order => '001',
601         }
602         user { "test1":
603           shell => "/bin/bash",
604           managehome => true,
605         }
606       EOS
607       puppet_apply(pp) do |r|
608         r.exit_code.should_not == 1
609       end
610
611       shell('su - test1 -c \'psql -U test1 -c "\q" test1\'') do |r|
612         r.exit_code.should == 2
613       end
614     end
615   end
616
617   describe 'postgresql.conf include' do
618     it "should support an 'include' directive at the end of postgresql.conf" do
619       pending('no support for include directive with centos 5/postgresql 8.1', :if => (node.facts['osfamily'] == 'RedHat' and node.facts['lsbmajdistrelease'] == '5'))
620       pp = <<-EOS
621         class pg_test {
622           class { 'postgresql::server': }
623
624           $pg_conf_include_file = "${postgresql::params::confdir}/postgresql_puppet_extras.conf"
625
626           file { $pg_conf_include_file :
627             content => 'max_connections = 123',
628             notify => Service['postgresqld'],
629           }
630         }
631         class { 'pg_test': }
632       EOS
633
634       puppet_apply(pp) do |r|
635         r.exit_code.should_not == 1
636       end
637
638       puppet_apply(pp) do |r|
639         r.exit_code.should be_zero
640       end
641
642       psql('--command="show max_connections" -t') do |r|
643         r.stdout.should =~ /123/
644         r.stderr.should be_empty
645         r.exit_code.should be_zero
646       end
647
648       pp = <<-EOS
649         class cleanup {
650           require postgresql::params
651
652           $pg_conf_include_file = "${postgresql::params::confdir}/postgresql_puppet_extras.conf"
653
654           file { $pg_conf_include_file :
655             ensure => absent
656           }
657         }
658         class { 'cleanup': }
659       EOS
660       puppet_apply(pp)
661     end
662   end
663 end