# # Create and destroy db # - name: Create DB become_user: "{{ pg_user }}" become: True postgresql_db: state: present name: "{{ db_name }}" login_user: "{{ pg_user }}" register: result - name: assert that module reports the db was created assert: that: - "result.changed == true" - "result.db =='{{ db_name }}'" - name: Check that database created become_user: "{{ pg_user }}" become: True shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - name: Run create on an already created db become_user: "{{ pg_user }}" become: True postgresql_db: state: present name: "{{ db_name }}" login_user: "{{ pg_user }}" register: result - name: assert that module reports the db was unchanged assert: that: - "result.changed == false" - name: Destroy DB become_user: "{{ pg_user }}" become: True postgresql_db: state: absent name: "{{ db_name }}" login_user: "{{ pg_user }}" register: result - name: assert that module reports the db was changed assert: that: - "result.changed == true" - name: Check that database was destroyed become_user: "{{ pg_user }}" become: True shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" - name: Destroy DB become_user: "{{ pg_user }}" become: True postgresql_db: state: absent name: "{{ db_name }}" login_user: "{{ pg_user }}" register: result - name: assert that removing an alreaady removed db makes no change assert: that: - "result.changed == false" # This corner case works to add but not to drop. This is sufficiently crazy # that I'm not going to attempt to fix it unless someone lets me know that they # need the functionality # # - postgresql_db: # state: 'present' # name: '"silly.""name"' # - shell: echo "select datname from pg_database where datname = 'silly.""name';" | psql # register: result # # - assert: # that: "result.stdout_lines[-1] == '(1 row)'" # - postgresql_db: # state: absent # name: '"silly.""name"' # - shell: echo "select datname from pg_database where datname = 'silly.""name';" | psql # register: result # # - assert: # that: "result.stdout_lines[-1] == '(0 rows)'" # # Test conn_limit, encoding, collate, ctype, template options # - name: Create a DB with conn_limit, encoding, collate, ctype, and template options become_user: "{{ pg_user }}" become: True postgresql_db: name: '{{ db_name }}' state: 'present' conn_limit: '100' encoding: 'LATIN1' lc_collate: 'pt_BR{{ locale_latin_suffix }}' lc_ctype: 'es_ES{{ locale_latin_suffix }}' template: 'template0' login_user: "{{ pg_user }}" - name: Check that the DB has all of our options become_user: "{{ pg_user }}" become: True shell: echo "select datname, datconnlimit, pg_encoding_to_char(encoding), datcollate, datctype from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - "'LATIN1' in result.stdout_lines[-2]" - "'pt_BR' in result.stdout_lines[-2]" - "'es_ES' in result.stdout_lines[-2]" - "'UTF8' not in result.stdout_lines[-2]" - "'en_US' not in result.stdout_lines[-2]" - "'100' in result.stdout_lines[-2]" - name: Check that running db cration with options a second time does nothing become_user: "{{ pg_user }}" become: True postgresql_db: name: '{{ db_name }}' state: 'present' conn_limit: '100' encoding: 'LATIN1' lc_collate: 'pt_BR{{ locale_latin_suffix }}' lc_ctype: 'es_ES{{ locale_latin_suffix }}' template: 'template0' login_user: "{{ pg_user }}" register: result - assert: that: - 'result.changed == False' - name: Check that attempting to change encoding returns an error become_user: "{{ pg_user }}" become: True postgresql_db: name: '{{ db_name }}' state: 'present' encoding: 'UTF8' lc_collate: 'pt_BR{{ locale_utf8_suffix }}' lc_ctype: 'es_ES{{ locale_utf8_suffix }}' template: 'template0' login_user: "{{ pg_user }}" register: result ignore_errors: True - assert: that: - 'result.failed == True' - name: Check that changing the conn_limit actually works become_user: "{{ pg_user }}" become: True postgresql_db: name: '{{ db_name }}' state: 'present' conn_limit: '200' encoding: 'LATIN1' lc_collate: 'pt_BR{{ locale_latin_suffix }}' lc_ctype: 'es_ES{{ locale_latin_suffix }}' template: 'template0' login_user: "{{ pg_user }}" register: result - assert: that: - 'result.changed == True' - name: Check that conn_limit has actually been set / updated to 200 become_user: "{{ pg_user }}" become: True shell: echo "SELECT datconnlimit AS conn_limit FROM pg_database WHERE datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - "'200' == '{{ result.stdout_lines[-2] | trim }}'" - name: Cleanup test DB become_user: "{{ pg_user }}" become: True postgresql_db: name: '{{ db_name }}' state: 'absent' login_user: "{{ pg_user }}" - shell: echo "select datname, pg_encoding_to_char(encoding), datcollate, datctype from pg_database where datname = '{{ db_name }}';" | psql -d postgres become_user: "{{ pg_user }}" become: True register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" # # Create and destroy user, test 'password' and 'encrypted' parameters # # unencrypted values are not supported on newer versions # do not run the encrypted: no tests if on 10+ - name: Get PostgreSQL version become_user: "{{ pg_user }}" become: True shell: "echo 'SHOW SERVER_VERSION' | psql --tuples-only --no-align --dbname postgres" register: postgres_version_resp - name: Print PostgreSQL server version debug: msg: "{{ postgres_version_resp.stdout }}" - set_fact: encryption_values: - 'yes' - set_fact: encryption_values: '{{ encryption_values }} + ["no"]' when: postgres_version_resp.stdout is version('10', '<=') - include: test_password.yml vars: encrypted: '{{ item }}' db_password1: 'secretù' # use UTF-8 loop: '{{ encryption_values }}' # BYPASSRLS role attribute was introduced in PostgreSQL 9.5, so # we want to test atrribute management differently depending # on the version. - set_fact: bypassrls_supported: "{{ postgres_version_resp.stdout is version('9.5.0', '>=') }}" # test 'no_password_change' and 'role_attr_flags' parameters - include: test_no_password_change.yml vars: no_password_changes: '{{ item }}' with_items: - 'yes' - 'no' ### TODO: fail_on_user # # Test db ownership # - name: Create an unprivileged user to own a DB become_user: "{{ pg_user }}" become: True postgresql_user: name: "{{ db_user1 }}" encrypted: 'yes' password: "md55c8ccfd9d6711fc69a7eae647fc54f51" login_user: "{{ pg_user }}" db: postgres - name: Create db with user ownership become_user: "{{ pg_user }}" become: True postgresql_db: name: "{{ db_name }}" state: "present" owner: "{{ db_user1 }}" login_user: "{{ pg_user }}" - name: Check that the user owns the newly created DB become_user: "{{ pg_user }}" become: True shell: echo "select pg_catalog.pg_get_userbyid(datdba) from pg_catalog.pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - "'{{ db_user1 }}' == '{{ result.stdout_lines[-2] | trim }}'" - name: Change the owner on an existing db become_user: "{{ pg_user }}" become: True postgresql_db: name: "{{ db_name }}" state: "present" owner: "{{ pg_user }}" login_user: "{{ pg_user }}" register: result - name: assert that ansible says it changed the db assert: that: - "result.changed == True" - name: Check that the user owns the newly created DB become_user: "{{ pg_user }}" become: True shell: echo "select pg_catalog.pg_get_userbyid(datdba) from pg_catalog.pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - "'{{ pg_user }}' == '{{ result.stdout_lines[-2] | trim }}'" - name: Cleanup db become_user: "{{ pg_user }}" become: True postgresql_db: name: "{{ db_name }}" state: "absent" login_user: "{{ pg_user }}" - name: Check that database was destroyed become_user: "{{ pg_user }}" become: True shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" - name: Cleanup test user become_user: "{{ pg_user }}" become: True postgresql_user: name: "{{ db_user1 }}" state: 'absent' login_user: "{{ pg_user }}" db: postgres - name: Check that they were removed become_user: "{{ pg_user }}" become: True shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" # # Test settings privileges # - name: Create db become_user: "{{ pg_user }}" become: True postgresql_db: name: "{{ db_name }}" state: "present" login_user: "{{ pg_user }}" - name: Create some tables on the db become_user: "{{ pg_user }}" become: True shell: echo "create table test_table1 (field text);" | psql {{ db_name }} - become_user: "{{ pg_user }}" become: True shell: echo "create table test_table2 (field text);" | psql {{ db_name }} - vars: db_password: 'secretù' # use UTF-8 block: - name: Create a user with some permissions on the db become_user: "{{ pg_user }}" become: True postgresql_user: name: "{{ db_user1 }}" encrypted: 'yes' password: "md5{{ (db_password ~ db_user1) | hash('md5')}}" db: "{{ db_name }}" priv: 'test_table1:INSERT,SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER/test_table2:INSERT/CREATE,CONNECT,TEMP' login_user: "{{ pg_user }}" - include: pg_authid_not_readable.yml - name: Check that the user has the requested permissions (table1) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table1';" | psql {{ db_name }} register: result_table1 - name: Check that the user has the requested permissions (table2) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table2';" | psql {{ db_name }} register: result_table2 - name: Check that the user has the requested permissions (database) become_user: "{{ pg_user }}" become: True shell: echo "select datacl from pg_database where datname='{{ db_name }}';" | psql {{ db_name }} register: result_database - assert: that: - "result_table1.stdout_lines[-1] == '(7 rows)'" - "'INSERT' in result_table1.stdout" - "'SELECT' in result_table1.stdout" - "'UPDATE' in result_table1.stdout" - "'DELETE' in result_table1.stdout" - "'TRUNCATE' in result_table1.stdout" - "'REFERENCES' in result_table1.stdout" - "'TRIGGER' in result_table1.stdout" - "result_table2.stdout_lines[-1] == '(1 row)'" - "'INSERT' == '{{ result_table2.stdout_lines[-2] | trim }}'" - "result_database.stdout_lines[-1] == '(1 row)'" - "'{{ db_user1 }}=CTc/{{ pg_user }}' in result_database.stdout_lines[-2]" - name: Add another permission for the user become_user: "{{ pg_user }}" become: True postgresql_user: name: "{{ db_user1 }}" encrypted: 'yes' password: "md55c8ccfd9d6711fc69a7eae647fc54f51" db: "{{ db_name }}" priv: 'test_table2:select' login_user: "{{ pg_user }}" register: results - name: Check that ansible reports it changed the user assert: that: - "results.changed == True" - name: Check that the user has the requested permissions (table2) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table2';" | psql {{ db_name }} register: result_table2 - assert: that: - "result_table2.stdout_lines[-1] == '(2 rows)'" - "'INSERT' in result_table2.stdout" - "'SELECT' in result_table2.stdout" # # Test priv setting via postgresql_privs module # (Depends on state from previous _user privs tests) # - name: Revoke a privilege become_user: "{{ pg_user }}" become: True postgresql_privs: type: "table" state: "absent" roles: "{{ db_user1 }}" privs: "INSERT" objs: "test_table2" db: "{{ db_name }}" login_user: "{{ pg_user }}" register: results - name: Check that ansible reports it changed the user assert: that: - "results.changed == True" - name: Check that the user has the requested permissions (table2) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table2';" | psql {{ db_name }} register: result_table2 - assert: that: - "result_table2.stdout_lines[-1] == '(1 row)'" - "'SELECT' == '{{ result_table2.stdout_lines[-2] | trim }}'" - name: Revoke many privileges on multiple tables become_user: "{{ pg_user }}" become: True postgresql_privs: state: "absent" roles: "{{ db_user1 }}" privs: "INSERT,select,UPDATE,TRUNCATE,REFERENCES,TRIGGER,delete" objs: "test_table2,test_table1" db: "{{ db_name }}" login_user: "{{ pg_user }}" register: results - name: Check that ansible reports it changed the user assert: that: - "results.changed == True" - name: Check that permissions were revoked (table1) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table1';" | psql {{ db_name }} register: result_table1 - name: Check that permissions were revoked (table2) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table2';" | psql {{ db_name }} register: result_table2 - assert: that: - "result_table1.stdout_lines[-1] == '(0 rows)'" - "result_table2.stdout_lines[-1] == '(0 rows)'" - name: Revoke database privileges become_user: "{{ pg_user }}" become: True postgresql_privs: type: "database" state: "absent" roles: "{{ db_user1 }}" privs: "Create,connect,TEMP" objs: "{{ db_name }}" db: "{{ db_name }}" login_user: "{{ pg_user }}" - name: Check that the user has the requested permissions (database) become_user: "{{ pg_user }}" become: True shell: echo "select datacl from pg_database where datname='{{ db_name }}';" | psql {{ db_name }} register: result_database - assert: that: - "result_database.stdout_lines[-1] == '(1 row)'" - "'{{ db_user1 }}' not in result_database.stdout" - name: Grant database privileges become_user: "{{ pg_user }}" become: True postgresql_privs: type: "database" state: "present" roles: "{{ db_user1 }}" privs: "CREATE,connect" objs: "{{ db_name }}" db: "{{ db_name }}" login_user: "{{ pg_user }}" register: results - name: Check that ansible reports it changed the user assert: that: - "results.changed == True" - name: Check that the user has the requested permissions (database) become_user: "{{ pg_user }}" become: True shell: echo "select datacl from pg_database where datname='{{ db_name }}';" | psql {{ db_name }} register: result_database - assert: that: - "result_database.stdout_lines[-1] == '(1 row)'" - "'{{ db_user1 }}=Cc' in result_database.stdout" - name: Grant a single privilege on a table become_user: "{{ pg_user }}" become: True postgresql_privs: state: "present" roles: "{{ db_user1 }}" privs: "INSERT" objs: "test_table1" db: "{{ db_name }}" login_user: "{{ pg_user }}" - name: Check that permissions were added (table1) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table1';" | psql {{ db_name }} register: result_table1 - assert: that: - "result_table1.stdout_lines[-1] == '(1 row)'" - "'{{ result_table1.stdout_lines[-2] | trim }}' == 'INSERT'" - name: Grant many privileges on multiple tables become_user: "{{ pg_user }}" become: True postgresql_privs: state: "present" roles: "{{ db_user1 }}" privs: 'INSERT,SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,trigger' objs: "test_table2,test_table1" db: "{{ db_name }}" login_user: "{{ pg_user }}" - name: Check that permissions were added (table1) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table1';" | psql {{ db_name }} register: result_table1 - name: Check that permissions were added (table2) become_user: "{{ pg_user }}" become: True shell: echo "select privilege_type from information_schema.role_table_grants where grantee='{{ db_user1 }}' and table_name='test_table2';" | psql {{ db_name }} register: result_table2 - assert: that: - "result_table1.stdout_lines[-1] == '(7 rows)'" - "'INSERT' in result_table1.stdout" - "'SELECT' in result_table1.stdout" - "'UPDATE' in result_table1.stdout" - "'DELETE' in result_table1.stdout" - "'TRUNCATE' in result_table1.stdout" - "'REFERENCES' in result_table1.stdout" - "'TRIGGER' in result_table1.stdout" - "result_table2.stdout_lines[-1] == '(7 rows)'" - "'INSERT' in result_table2.stdout" - "'SELECT' in result_table2.stdout" - "'UPDATE' in result_table2.stdout" - "'DELETE' in result_table2.stdout" - "'TRUNCATE' in result_table2.stdout" - "'REFERENCES' in result_table2.stdout" - "'TRIGGER' in result_table2.stdout" # # Cleanup # - name: Cleanup db become_user: "{{ pg_user }}" become: True postgresql_db: name: "{{ db_name }}" state: "absent" login_user: "{{ pg_user }}" - name: Check that database was destroyed become_user: "{{ pg_user }}" become: True shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" - name: Cleanup test user become_user: "{{ pg_user }}" become: True postgresql_user: name: "{{ db_user1 }}" state: 'absent' login_user: "{{ pg_user }}" db: postgres - name: Check that they were removed become_user: "{{ pg_user }}" become: True shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" # # Test login_user functionality # - name: Create a user to test login module parameters become: True become_user: "{{ pg_user }}" postgresql_user: name: "{{ db_user1 }}" state: "present" encrypted: 'yes' password: "password" role_attr_flags: "CREATEDB,LOGIN,CREATEROLE" login_user: "{{ pg_user }}" db: postgres - name: Create db postgresql_db: name: "{{ db_name }}" state: "present" login_user: "{{ db_user1 }}" login_password: "password" login_host: "localhost" - name: Check that database created become: True become_user: "{{ pg_user }}" shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - name: Create a user postgresql_user: name: "{{ db_user2 }}" state: "present" encrypted: 'yes' password: "md55c8ccfd9d6711fc69a7eae647fc54f51" db: "{{ db_name }}" login_user: "{{ db_user1 }}" login_password: "password" login_host: "localhost" - name: Check that it was created become: True become_user: "{{ pg_user }}" shell: echo "select * from pg_user where usename='{{ db_user2 }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(1 row)'" - name: Grant database privileges postgresql_privs: type: "database" state: "present" roles: "{{ db_user2 }}" privs: "CREATE,connect" objs: "{{ db_name }}" db: "{{ db_name }}" login: "{{ db_user1 }}" password: "password" host: "localhost" - name: Check that the user has the requested permissions (database) become: True become_user: "{{ pg_user }}" shell: echo "select datacl from pg_database where datname='{{ db_name }}';" | psql {{ db_name }} register: result_database - assert: that: - "result_database.stdout_lines[-1] == '(1 row)'" - "'{{ db_user2 }}=Cc' in result_database.stdout" - name: Remove user postgresql_user: name: "{{ db_user2 }}" state: 'absent' priv: "ALL" db: "{{ db_name }}" login_user: "{{ db_user1 }}" login_password: "password" login_host: "localhost" - name: Check that they were removed become: True become_user: "{{ pg_user }}" shell: echo "select * from pg_user where usename='{{ db_user2 }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" - name: Destroy DB postgresql_db: state: absent name: "{{ db_name }}" login_user: "{{ db_user1 }}" login_password: "password" login_host: "localhost" - name: Check that database was destroyed become: True become_user: "{{ pg_user }}" shell: echo "select datname from pg_database where datname = '{{ db_name }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'" # Test ssl. # Restricted using Debian family because of there are errors on other distributions # that not related with PostgreSQL or psycopg2 SSL support. # The tests' key point is to be sure that ssl options work in general - include: ssl.yml when: ansible_os_family == 'Debian' and postgres_version_resp.stdout is version('9.4', '>=') # Test postgresql_set - include: postgresql_set.yml when: postgres_version_resp.stdout is version('9.4', '>=') # Verify different session_role scenarios - include: session_role.yml # Test postgresql_idx module - include: postgresql_idx.yml # Test postgresql_query module - include: postgresql_query.yml # Verify postgresql_ping module - include: postgresql_ping.yml db_name_nonexist=fake_db # Test postgresql_tablespace module - include: postgresql_tablespace.yml # Test postgresql_db module, specific options: - include: postgresql_db.yml # Test postgresql_privs - include: postgresql_privs.yml # Test postgresql_info module - include: postgresql_info.yml # Test default_privs with target_role - include: test_target_role.yml when: postgres_version_resp.stdout is version('9.1', '>=') # Test postgresql_copy module - include: postgresql_copy.yml when: postgres_version_resp.stdout is version('9.4', '>=') # Test postgresql_ext. # pg_extension system view is available from PG 9.1. # The tests are restricted by Fedora because there will be errors related with # attempts to change the environment during postgis installation or # missing postgis package in repositories. # Anyway, these tests completely depend on Postgres version, # not specific distributions. - include: postgresql_ext.yml when: postgres_version_resp.stdout is version('9.1', '>=') and ansible_distribution == 'Fedora' # Test postgresql_slot module. # Physical replication slots are available from PostgreSQL 9.4 - include: postgresql_slot.yml when: postgres_version_resp.stdout is version('9.4', '>=') # Test postgresql_schema module - include: postgresql_schema.yml # Test postgresql_membership module - include: postgresql_membership.yml # Test postgresql_table module - include: postgresql_table.yml # Test postgresql_lang module. # To implement tests, it needs to install some additional packages # that may cause problems on different distributions, # so I restricted the tests using CentOS because the results # depend only on Postgres version # (CentOS 6 repo contains the oldest PG version in these tests - 9.0): - include: postgresql_lang.yml when: ansible_distribution == 'CentOS' # Test postgresql_owner module - include: postgresql_owner.yml # dump/restore tests per format # ============================================================ - include: state_dump_restore.yml test_fixture=user file=dbdata.sql - include: state_dump_restore.yml test_fixture=user file=dbdata.sql.gz - include: state_dump_restore.yml test_fixture=user file=dbdata.sql.bz2 - include: state_dump_restore.yml test_fixture=user file=dbdata.sql.xz - include: state_dump_restore.yml test_fixture=user file=dbdata.tar - include: state_dump_restore.yml test_fixture=user file=dbdata.tar.gz - include: state_dump_restore.yml test_fixture=user file=dbdata.tar.bz2 - include: state_dump_restore.yml test_fixture=user file=dbdata.tar.xz # dump/restore tests per other logins # ============================================================ - include: state_dump_restore.yml file=dbdata.tar test_fixture=admin # postgres_pg_hba module checks # ============================================================ - include: postgresql_pg_hba.yml # # Cleanup # - name: Cleanup test user become: True become_user: "{{ pg_user }}" postgresql_user: name: "{{ db_user1 }}" state: 'absent' db: postgres login_user: "{{ pg_user }}" - name: Check that they were removed become: True become_user: "{{ pg_user }}" shell: echo "select * from pg_user where usename='{{ db_user1 }}';" | psql -d postgres register: result - assert: that: - "result.stdout_lines[-1] == '(0 rows)'"