From 04c999f0f8d1062e73333931c922e6cd215dd741 Mon Sep 17 00:00:00 2001 From: Andrey Klychkov Date: Tue, 5 Nov 2019 13:26:51 +0300 Subject: [PATCH] postgresql_idx: add stat mode support (#64138) * postgresql_idx: add stat mode support * postgresql_idx: add stat mode support, add changelog * postgresql_idx: add stat mode support, fix CI --- .../64138-postgresql_idx_add_state_stat.yml | 2 + .../database/postgresql/postgresql_idx.py | 58 ++++++++++++++++--- .../tasks/postgresql_idx_initial.yml | 47 +++++++++++++++ 3 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/64138-postgresql_idx_add_state_stat.yml diff --git a/changelogs/fragments/64138-postgresql_idx_add_state_stat.yml b/changelogs/fragments/64138-postgresql_idx_add_state_stat.yml new file mode 100644 index 00000000000..a73296dbe89 --- /dev/null +++ b/changelogs/fragments/64138-postgresql_idx_add_state_stat.yml @@ -0,0 +1,2 @@ +minor_changes: +- postgresql_idx - add a new option ``stat`` to the ``state`` parameter (https://github.com/ansible/ansible/pull/64138). diff --git a/lib/ansible/modules/database/postgresql/postgresql_idx.py b/lib/ansible/modules/database/postgresql/postgresql_idx.py index e4b9c5390ff..6a76ad2eda6 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_idx.py +++ b/lib/ansible/modules/database/postgresql/postgresql_idx.py @@ -49,11 +49,15 @@ options: state: description: - Index state. - - I(state=present) implies the index will be created if it does not exist. - - I(state=absent) implies the index will be dropped if it exists. + - C(present) implies the index will be created if it does not exist. + - C(absent) implies the index will be dropped if it exists. + - C(stat) returns index statistics information from the ``pg_stat_user_indexes`` standard view. + Supported from Ansible 2.10. + - "When C(stat) following parameters will be ignored:" + - I(schema), I(table), I(columns), I(cond), I(idxtype), I(tablespace), I(concurrent), I(cascade). type: str default: present - choices: [ absent, present ] + choices: [ absent, present, stat ] table: description: - Table to create index on it. @@ -195,6 +199,12 @@ EXAMPLES = r''' columns: id,comment idxname: test_idx cond: id > 1 + +- name: Get index statistics of test_idx from mydb + postgresql_idx: + db: mydb + idxname: test_idx + state: stat ''' RETURN = r''' @@ -233,6 +243,11 @@ valid: returned: always type: bool sample: true +stat: + description: Index statistics. + returned: if state is stat + type: bool + sample: { 'idx_scan': 19239, 'idx_tup_read': 929329, 'idx_tup_fetch': 4949459 } ''' try: @@ -313,6 +328,21 @@ class Index(object): self.__exists_in_db() return self.info + def get_stat(self): + """Get and return index statistics. + + Return index statistics dictionary if index exists, otherwise False. + """ + query = ("SELECT * FROM pg_stat_user_indexes " + "WHERE indexrelname = '%s' " + "AND schemaname = '%s'" % (self.name, self.schema)) + + result = exec_sql(self, query, add_to_executed=False) + if result: + return [dict(row) for row in result] + else: + return False + def __exists_in_db(self): """Check index existence, collect info, add it to self.info dict. @@ -363,7 +393,6 @@ class Index(object): if self.exists: return False - changed = False if idxtype is None: idxtype = "BTREE" @@ -410,7 +439,6 @@ class Index(object): default False concurrent (bool) -- build index in concurrent mode, default True """ - changed = False if not self.exists: return False @@ -445,7 +473,7 @@ def main(): argument_spec.update( idxname=dict(type='str', required=True, aliases=['name']), db=dict(type='str', aliases=['login_db']), - state=dict(type='str', default='present', choices=['absent', 'present']), + state=dict(type='str', default='present', choices=['absent', 'present', 'stat']), concurrent=dict(type='bool', default=True), table=dict(type='str'), idxtype=dict(type='str', aliases=['type']), @@ -506,7 +534,14 @@ def main(): # # check_mode start if module.check_mode: - if state == 'present' and index.exists: + if state == 'stat': + if index.exists: + kw['stat'] = index.get_stat() + + kw['changed'] = False + module.exit_json(**kw) + + elif state == 'present' and index.exists: kw['changed'] = False module.exit_json(**kw) @@ -524,7 +559,14 @@ def main(): # check_mode end # - if state == "present": + if state == 'stat': + if index.exists: + kw['stat'] = index.get_stat() + + kw['changed'] = False + module.exit_json(**kw) + + elif state == "present": if idxtype and idxtype.upper() not in VALID_IDX_TYPES: module.fail_json(msg="Index type '%s' of %s is not in valid types" % (idxtype, idxname)) diff --git a/test/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml b/test/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml index 28eb70e5468..0f16e201af0 100644 --- a/test/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml +++ b/test/integration/targets/postgresql_idx/tasks/postgresql_idx_initial.yml @@ -253,6 +253,53 @@ - result.schema == 'public' - result.query == 'CREATE INDEX CONCURRENTLY test1_idx ON public.test_table USING BTREE (id) WHERE id > 1 AND id != 10' +# Get idx stat in check mode +- name: postgresql_idx - test state stat in check_mode + become_user: "{{ pg_user }}" + become: yes + postgresql_idx: + db: postgres + login_user: "{{ pg_user }}" + idxname: test1_idx + state: stat + check_mode: yes + register: result + +- assert: + that: + - result is not changed + - result.tblname == 'test_table' + - result.name == 'test1_idx' + - result.state == 'present' + - result.valid != '' + - result.tblspace == '' + - result.storage_params == [] + - result.schema == 'public' + - result.stat != {} + +# Get idx stat +- name: postgresql_idx - test state stat + become_user: "{{ pg_user }}" + become: yes + postgresql_idx: + db: postgres + login_user: "{{ pg_user }}" + idxname: test1_idx + state: stat + register: result + +- assert: + that: + - result is not changed + - result.tblname == 'test_table' + - result.name == 'test1_idx' + - result.state == 'present' + - result.valid != '' + - result.tblspace == '' + - result.storage_params == [] + - result.schema == 'public' + - result.stat != {} + # Drop index from specific schema with cascade in check_mode - name: postgresql_idx - drop index from specific schema cascade in check_mode become_user: "{{ pg_user }}"