Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for partitions #391

Closed
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions plugins/modules/postgresql_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@
default: ''
aliases:
- login_db
partition_by:
description:
- Type of the table partitioning. Possibil values are range, list, and hash.
SiL3x marked this conversation as resolved.
Show resolved Hide resolved
type: str
partition_on:
description:
- Columns that are used for partitioning
SiL3x marked this conversation as resolved.
Show resolved Hide resolved
type: list
elements: str
session_role:
description:
- Switch to session_role after connecting.
Expand Down Expand Up @@ -312,7 +321,7 @@ def __exists_in_db(self):
return False

def create(self, columns='', params='', tblspace='',
unlogged=False, owner=''):
unlogged=False, owner='', partition_by='', partition_on=''):
"""
Create table.
If table exists, check passed args (params, tblspace, owner) and,
Expand All @@ -324,6 +333,8 @@ def create(self, columns='', params='', tblspace='',
owner - table owner.
unlogged - create unlogged table.
columns - column string (comma separated).
partition_by - type of partitioning (range, hash, list).
partition_on - column string (comman separated).
"""
name = pg_quote_identifier(self.name, 'table')

Expand Down Expand Up @@ -373,6 +384,9 @@ def create(self, columns='', params='', tblspace='',
if tblspace:
query += ' TABLESPACE "%s"' % tblspace

if partition_by:
query += " PARTITION BY %s (%s)" % (partition_by, partition_on)

if exec_sql(self, query, return_bool=True):
changed = True

Expand Down Expand Up @@ -482,6 +496,8 @@ def main():
session_role=dict(type='str'),
cascade=dict(type='bool', default=False),
trust_input=dict(type='bool', default=True),
partition_by=dict(type='str'),
partition_on=dict(type='list', elements='str'),
)
module = AnsibleModule(
argument_spec=argument_spec,
Expand All @@ -499,6 +515,8 @@ def main():
storage_params = module.params['storage_params']
truncate = module.params['truncate']
columns = module.params['columns']
partition_by = module.params['partition_by']
partition_on = module.params['partition_on']
cascade = module.params['cascade']
session_role = module.params['session_role']
trust_input = module.params['trust_input']
Expand All @@ -512,20 +530,21 @@ def main():
module.warn("cascade=true is ignored when state=present")

# Check mutual exclusive parameters:
if state == 'absent' and (truncate or newname or columns or tablespace or like or storage_params or unlogged or owner or including):
if state == 'absent' and (truncate or newname or columns or tablespace or like or storage_params or unlogged or owner or including
or partition_by or partition_on):
module.fail_json(msg="%s: state=absent is mutually exclusive with: "
"truncate, rename, columns, tablespace, "
"including, like, storage_params, unlogged, owner" % table)
"including, like, storage_params, unlogged, owner, partition_by, partition_on" % table)

if truncate and (newname or columns or like or unlogged or storage_params or owner or tablespace or including):
if truncate and (newname or columns or like or unlogged or storage_params or owner or tablespace or including or partition_by or partition_on):
module.fail_json(msg="%s: truncate is mutually exclusive with: "
"rename, columns, like, unlogged, including, "
"storage_params, owner, tablespace" % table)
"storage_params, owner, tablespace, partition_by, partition_on" % table)

if newname and (columns or like or unlogged or storage_params or owner or tablespace or including):
if newname and (columns or like or unlogged or storage_params or owner or tablespace or including or partition_by or partition_on):
module.fail_json(msg="%s: rename is mutually exclusive with: "
"columns, like, unlogged, including, "
"storage_params, owner, tablespace" % table)
"storage_params, owner, tablespace, partition_by, partition_on" % table)

if like and columns:
module.fail_json(msg="%s: like and columns params are mutually exclusive" % table)
Expand All @@ -544,6 +563,9 @@ def main():
if columns:
columns = ','.join(columns)

if partition_on:
partition_on = ','.join(partition_on)

##############
# Do main job:
table_obj = Table(table, module, cursor)
Expand Down Expand Up @@ -576,7 +598,7 @@ def main():

elif state == 'present' and not like:
changed = table_obj.create(columns, storage_params,
tablespace, unlogged, owner)
tablespace, unlogged, owner, partition_by, partition_on)

elif state == 'present' and like:
changed = table_obj.create_like(like, including, tablespace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,51 @@
- result is changed
- result.queries == ['ALTER TABLE "public"."test_schema_table" RENAME TO "new_test_schema_table"']

#
# Create and drop partitioned table:
#

- name: postgresql_table - create table with partition by range
postgresql_table:
db: postgres
login_port: 5432
login_user: "{{ pg_user }}"
name: test5
columns: id int
partition_by: RANGE
partition_on: id
register: result

- assert:
that:
- result is changed
- result.queries == ['CREATE TABLE "test5" (id int) PARTITION BY RANGE (id)']

- name: postgresql_table - check that table exists after the previous step
become_user: "{{ pg_user }}"
become: true
postgresql_query:
db: postgres
login_user: "{{ pg_user }}"
query: "SELECT 1 FROM pg_stat_all_tables WHERE relname = 'test5'"
ignore_errors: true
register: result

- assert:
that:
- result.rowcount == 1

- name: postgresql_table - drop table
become_user: "{{ pg_user }}"
become: true
postgresql_table:
db: postgres
login_user: "{{ pg_user }}"
name: test5
state: absent
register: result
ignore_errors: true

############################
# Test trust_input parameter
- name: postgresql_table - check trust_input
Expand Down
18 changes: 10 additions & 8 deletions tests/integration/targets/setup_postgresql_db/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,16 @@
group: '{{ pg_group }}'
mode: '0644'

- name: Generate locales (Debian)
locale_gen:
name: '{{ item }}'
state: present
with_items:
- pt_BR
- es_ES
when: ansible_os_family == 'Debian'
### Comment: This block caused the tests to crash

#- name: Generate locales (Debian)
Comment on lines +130 to +132
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Comment: This block caused the tests to crash
#- name: Generate locales (Debian)
### Comment: This block caused the tests to crash
#- name: Generate locales (Debian)

Do you run them with --docker ?, e.g:

ansible-test integration <target_name> --docker ubuntu2004 -vvv > ~/test.log

i run the tests today and they were green

Copy link
Author

@SiL3x SiL3x Jan 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran them exactly like that and they crashed with:

ERROR! couldn't resolve module/action 'locale_gen'. This often indicates a misspelling, missing collection, or incorrect module path.

The error appears to be in '/root/ansible_collections/community/postgresql/tests/output/.tmp/integration/postgresql_table-l3c1vxf2-ÅÑŚÌβŁÈ/tests/integration/targets/setup_postgresql_db/tasks/main.yml': line 132, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


- name: Generate locales (Debian)
  ^ here

Also apparently nothing breaks when the block is out commented.

test.log

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SiL3x i've just checked out your branch, uncommented this block and run the tests locally:

$ ansible-test integration postgresql_table --docker ubuntu2004 -vvv > ~/test.log
WARNING: A Python 3.8 interpreter was found at "/usr/bin/python3.8", yet a matching pip was not found.
[WARNING]: running playbook inside collection community.postgresql
[WARNING]: Collection community.general does not support Ansible version 2.10.6
[WARNING]: Updating cache and auto-installing missing dependency: python3-apt
[WARNING]: Consider using the get_url or uri module rather than running 'wget'.
If you need to use command because get_url or uri is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
[WARNING]: Module remote_tmp /var/lib/postgresql/.ansible/tmp did not exist and
was created with a mode of 0700, this may cause issues when running as another
user. To avoid this, create the remote_tmp dir with the correct permissions
manually
[WARNING]: The value "True" (type bool) was converted to "'True'" (type
string). If this does not look like what you expect, quote the entire value to
ensure it does not change.
WARNING: Reviewing previous 1 warning(s):
WARNING: A Python 3.8 interpreter was found at "/usr/bin/python3.8", yet a matching pip was not found.

They pass.
Could you please uncomment the block and push? Let's see what our CI will say.

# locale_gen:
# name: '{{ item }}'
# state: present
# with_items:
# - pt_BR
# - es_ES
# when: ansible_os_family == 'Debian'

- block:
- name: Install langpacks (RHEL8)
Expand Down