diff --git a/lib/ansible/modules/database/postgresql/postgresql_subscription.py b/lib/ansible/modules/database/postgresql/postgresql_subscription.py index f89382515ef..ba32e1c0a85 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_subscription.py +++ b/lib/ansible/modules/database/postgresql/postgresql_subscription.py @@ -39,7 +39,6 @@ options: - The subscription state. - C(present) implies that if I(name) subscription doesn't exist, it will be created. - C(absent) implies that if I(name) subscription exists, it will be removed. - - C(stat) implies that if I(name) subscription exists, returns current configuration. - C(refresh) implies that if I(name) subscription exists, it will be refreshed. Fetch missing table information from publisher. Always returns ``changed`` is ``True``. This will start replication of tables that were added to the subscribed-to publications @@ -48,13 +47,8 @@ options: should be copied once the replication starts. - For more information about C(refresh) see U(https://www.postgresql.org/docs/current/sql-altersubscription.html). type: str - choices: [ absent, present, refresh, stat ] + choices: [ absent, present, refresh ] default: present - relinfo: - description: - - Get information of the state for each replicated relation in the subscription. - type: bool - default: false owner: description: - Subscription owner. @@ -93,6 +87,7 @@ notes: seealso: - module: postgresql_publication +- module: postgresql_info - name: CREATE SUBSCRIPTION reference description: Complete reference of the CREATE SUBSCRIPTION command documentation. link: https://www.postgresql.org/docs/current/sql-createsubscription.html @@ -145,15 +140,6 @@ EXAMPLES = r''' name: acme state: refresh -- name: > - Return the configuration of subscription acme if exists in mydb database. - Also return state of replicated relations. - postgresql_subscription: - db: mydb - name: acme - state: stat - relinfo: yes - - name: Drop acme subscription from mydb with dependencies (cascade=yes) postgresql_subscription: db: mydb @@ -273,9 +259,6 @@ class PgSubscription(): name (str): The name of the subscription. db (str): The database name the subscription will be associated with. - Kwargs: - relinfo (bool): Flag indicates the relation information is needed. - Attributes: module (AnsibleModule): Object of AnsibleModule class. cursor (cursor): Cursor object of psycopg2 library to work with PostgreSQL. @@ -285,12 +268,11 @@ class PgSubscription(): exists (bool): Flag indicates the subscription exists or not. """ - def __init__(self, module, cursor, name, db, relinfo): + def __init__(self, module, cursor, name, db): self.module = module self.cursor = cursor self.name = name self.db = db - self.relinfo = relinfo self.executed_queries = [] self.attrs = { 'owner': None, @@ -299,7 +281,6 @@ class PgSubscription(): 'conninfo': {}, 'slotname': None, 'publications': [], - 'relinfo': None, } self.empty_attrs = deepcopy(self.attrs) self.exists = self.check_subscr() @@ -340,9 +321,6 @@ class PgSubscription(): except ValueError: self.attrs['conninfo'][tmp[0]] = tmp[1] - if self.relinfo: - self.attrs['relinfo'] = self.__get_rel_info() - return True def create(self, connparams, publications, subsparams, check_mode=True): @@ -564,24 +542,6 @@ class PgSubscription(): else: return False - def __get_rel_info(self): - """Get and return state of relations replicated by the subscription. - - Returns: - List of dicts containing relations state if successful, False otherwise. - """ - query = ("SELECT c.relname, r.srsubstate, r.srsublsn " - "FROM pg_catalog.pg_subscription_rel r " - "JOIN pg_catalog.pg_subscription s ON s.oid = r.srsubid " - "JOIN pg_catalog.pg_class c ON c.oid = r.srrelid " - "WHERE s.subname = %(name)s") - - result = exec_sql(self, query, query_params={'name': self.name}, add_to_executed=False) - if result: - return [dict(row) for row in result] - else: - return False - def __exec_sql(self, query, check_mode=False): """Execute SQL query. @@ -615,13 +575,12 @@ def main(): argument_spec.update( name=dict(type='str', required=True), db=dict(type='str', required=True, aliases=['login_db']), - state=dict(type='str', default='present', choices=['absent', 'present', 'refresh', 'stat']), + state=dict(type='str', default='present', choices=['absent', 'present', 'refresh']), publications=dict(type='list', elements='str'), connparams=dict(type='dict'), cascade=dict(type='bool', default=False), owner=dict(type='str'), subsparams=dict(type='dict'), - relinfo=dict(type='bool', default=False), ) module = AnsibleModule( argument_spec=argument_spec, @@ -637,7 +596,6 @@ def main(): owner = module.params['owner'] subsparams = module.params['subsparams'] connparams = module.params['connparams'] - relinfo = module.params['relinfo'] if state == 'present' and cascade: module.warn('parameter "cascade" is ignored when state is not absent') @@ -669,18 +627,13 @@ def main(): ################################### # Create object and do rock'n'roll: - subscription = PgSubscription(module, cursor, name, db, relinfo) + subscription = PgSubscription(module, cursor, name, db) if subscription.exists: initial_state = deepcopy(subscription.attrs) final_state = deepcopy(initial_state) - # If module.check_mode=True, nothing will be changed: - if state == 'stat': - # Information has been collected already, so nothing is needed: - pass - - elif state == 'present': + if state == 'present': if not subscription.exists: if subsparams: subsparams = convert_subscr_params(subsparams) @@ -712,9 +665,8 @@ def main(): # Always returns True: changed = subscription.refresh(check_mode=module.check_mode) - # Get final subscription info if needed: - if state != 'stat': - final_state = subscription.get_info() + # Get final subscription info: + final_state = subscription.get_info() # Connection is not needed any more: cursor.close() diff --git a/test/integration/targets/postgresql_subscription/tasks/postgresql_subscription_initial.yml b/test/integration/targets/postgresql_subscription/tasks/postgresql_subscription_initial.yml index f72cc57d198..6dda6fc1abd 100644 --- a/test/integration/targets/postgresql_subscription/tasks/postgresql_subscription_initial.yml +++ b/test/integration/targets/postgresql_subscription/tasks/postgresql_subscription_initial.yml @@ -59,60 +59,16 @@ - result.final_state.conninfo.user == '{{ replication_role }}' - result.final_state.conninfo.password == '{{ replication_pass }}' - ################# - # Test mode: stat - ################# - - - name: Stat mode in check mode + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat - check_mode: yes + query: "SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true - - result.final_state == result.initial_state - - result.final_state.owner == '{{ pg_user }}' - - result.final_state.enabled == true - - result.final_state.publications == ["{{ test_pub }}"] - - result.final_state.synccommit == true - - result.final_state.slotname == '{{ test_subscription }}' - - result.final_state.conninfo.dbname == '{{ test_db }}' - - result.final_state.conninfo.host == '127.0.0.1' - - result.final_state.conninfo.port == {{ master_port }} - - result.final_state.conninfo.user == '{{ replication_role }}' - - result.final_state.conninfo.password == '{{ replication_pass }}' - - - name: Stat mode - <<: *task_parameters - postgresql_subscription: - <<: *pg_parameters - login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat - - - assert: - that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true - - result.final_state == result.initial_state - - result.final_state.owner == '{{ pg_user }}' - - result.final_state.enabled == true - - result.final_state.publications == ["{{ test_pub }}"] - - result.final_state.synccommit == true - - result.final_state.slotname == '{{ test_subscription }}' - - result.final_state.conninfo.dbname == '{{ test_db }}' - - result.final_state.conninfo.host == '127.0.0.1' - - result.final_state.conninfo.port == {{ master_port }} - - result.final_state.conninfo.user == '{{ replication_role }}' - - result.final_state.conninfo.password == '{{ replication_pass }}' + - result.rowcount == 1 ################### # Test mode: absent @@ -133,19 +89,16 @@ - result.queries == ["DROP SUBSCRIPTION {{ test_subscription }}"] - result.final_state == result.initial_state - - name: Check the subscription exists + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: "SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true + - result.rowcount == 1 - name: Drop subscription <<: *task_parameters @@ -161,19 +114,16 @@ - result.queries == ["DROP SUBSCRIPTION {{ test_subscription }}"] - result.final_state != result.initial_state - - name: Check the subscription doesn't exist + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: "SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == false + - result.rowcount == 0 ################## # Test owner param @@ -216,20 +166,19 @@ - result.initial_state == result.final_state - result.final_state.owner == '{{ test_role1 }}' - - name: Check owner + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription AS s + JOIN pg_catalog.pg_roles AS r ON s.subowner = r.oid + WHERE subname = '{{ test_subscription }}' and r.rolname = '{{ test_role1 }}' - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true - - result.initial_state.owner == '{{ test_role1 }}' + - result.rowcount == 1 - name: Set another owner in check mode <<: *task_parameters @@ -249,20 +198,19 @@ - result.final_state.owner == '{{ test_role1 }}' - result.queries == ['ALTER SUBSCRIPTION {{ test_subscription }} OWNER TO "{{ test_role2 }}"'] - - name: Check owner + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription AS s + JOIN pg_catalog.pg_roles AS r ON s.subowner = r.oid + WHERE subname = '{{ test_subscription }}' and r.rolname = '{{ test_role1 }}' - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true - - result.initial_state.owner == '{{ test_role1 }}' + - result.rowcount == 1 - name: Set another owner <<: *task_parameters @@ -281,24 +229,23 @@ - result.final_state.owner == '{{ test_role2 }}' - result.queries == ['ALTER SUBSCRIPTION {{ test_subscription }} OWNER TO "{{ test_role2 }}"'] - - name: Check owner + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription AS s + JOIN pg_catalog.pg_roles AS r ON s.subowner = r.oid + WHERE subname = '{{ test_subscription }}' and r.rolname = '{{ test_role2 }}' - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true - - result.initial_state.owner == '{{ test_role2 }}' + - result.rowcount == 1 - ############################## - # Test cascade and owner param - ############################## + ############## + # Test cascade + ############## - name: Drop subscription cascade in check mode <<: *task_parameters @@ -316,19 +263,16 @@ - result.queries == ["DROP SUBSCRIPTION {{ test_subscription }} CASCADE"] - result.final_state == result.initial_state - - name: Check the subscription exists + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: "SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == true + - result.rowcount == 1 - name: Drop subscription cascade <<: *task_parameters @@ -345,19 +289,16 @@ - result.queries == ["DROP SUBSCRIPTION {{ test_subscription }} CASCADE"] - result.final_state != result.initial_state - - name: Check the subscription doesn't exist + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: "SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result is not changed - - result.name == '{{ test_subscription }}' - - result.exists == false + - result.rowcount == 0 ########################### # Test subsparams parameter @@ -390,19 +331,18 @@ - result.final_state.enabled == false - result.final_state.synccommit == false - - name: Stat mode + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}' + AND subenabled = 'f' AND subsynccommit = 'false' - assert: that: - - result.name == '{{ test_subscription }}' - - result.final_state.enabled == false - - result.final_state.synccommit == false + - result.rowcount == 1 - name: Enable changed params <<: *task_parameters @@ -424,19 +364,18 @@ - result.final_state.enabled == true - result.final_state.synccommit == true - - name: Stat mode + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}' + AND subenabled = 't' AND subsynccommit = 'true' - assert: that: - - result.name == '{{ test_subscription }}' - - result.final_state.enabled == true - - result.final_state.synccommit == true + - result.rowcount == 1 - name: Enable the same params again <<: *task_parameters @@ -483,18 +422,18 @@ - result.final_state.publications == ['{{ test_pub }}'] - result.queries == ['ALTER SUBSCRIPTION {{ test_subscription }} SET PUBLICATION {{ test_pub }}, {{ test_pub2 }}'] - - name: Check publications + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}' + AND subpublications = '{"{{ test_pub }}"}' - assert: that: - - result.name == '{{ test_subscription }}' - - result.final_state.publications == ['{{ test_pub }}'] + - result.rowcount == 1 - name: Change publications <<: *task_parameters @@ -515,18 +454,18 @@ - result.final_state.publications == ['{{ test_pub }}', '{{ test_pub2 }}'] - result.queries == ['ALTER SUBSCRIPTION {{ test_subscription }} SET PUBLICATION {{ test_pub }}, {{ test_pub2 }}'] - - name: Check publications + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: > + SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}' + AND subpublications = '{"{{ test_pub }}", "{{ test_pub2 }}"}' - assert: that: - - result.name == '{{ test_subscription }}' - - result.final_state.publications == ['{{ test_pub }}', '{{ test_pub2 }}'] + - result.rowcount == 1 - name: Change publications with the same values again <<: *task_parameters @@ -547,6 +486,19 @@ - result.final_state.publications == ['{{ test_pub }}', '{{ test_pub2 }}'] - result.queries == [] + - name: Check + <<: *task_parameters + postgresql_query: + <<: *pg_parameters + login_port: '{{ replica_port }}' + query: > + SELECT subname FROM pg_subscription WHERE subname = '{{ test_subscription }}' + AND subpublications = '{"{{ test_pub }}", "{{ test_pub2 }}"}' + + - assert: + that: + - result.rowcount == 1 + ###################### # Test update conninfo ###################### @@ -581,7 +533,6 @@ login_port: '{{ replica_port }}' name: '{{ test_subscription }}' state: present - relinfo: yes connparams: host: 127.0.0.1 port: '{{ master_port }}' @@ -597,18 +548,16 @@ - result.queries == ["ALTER SUBSCRIPTION {{ test_subscription }} CONNECTION 'host=127.0.0.1 port={{ master_port }} user={{ replication_role }} password={{ replication_pass }} dbname={{ test_db }} connect_timeout={{ conn_timeout }}'"] - result.initial_state.conninfo != result.final_state.conninfo - - name: Check publications + - name: Check <<: *task_parameters - postgresql_subscription: + postgresql_query: <<: *pg_parameters login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat + query: "SELECT * FROM pg_subscription WHERE subname = '{{ test_subscription }}'" - assert: that: - - result.name == '{{ test_subscription }}' - - result.final_state.conninfo.connect_timeout == {{ conn_timeout }} + - result.query_result[0].subconninfo == "host=127.0.0.1 port={{ master_port }} user={{ replication_role }} password={{ replication_pass }} dbname={{ test_db }} connect_timeout={{ conn_timeout }}" - name: Try to change conninfo again with the same values <<: *task_parameters @@ -666,25 +615,6 @@ - result.name == '{{ test_subscription }}' - result.queries == ["ALTER SUBSCRIPTION {{ test_subscription }} REFRESH PUBLICATION"] - #################### - # Test relinfo param - #################### - - - name: Get relinfo - <<: *task_parameters - postgresql_subscription: - <<: *pg_parameters - login_port: '{{ replica_port }}' - name: '{{ test_subscription }}' - state: stat - relinfo: yes - - - assert: - that: - - result.name == '{{ test_subscription }}' - - result.final_state.relinfo[0].relname == '{{ test_table1 }}' - - result.final_state == result.initial_state - ########## # Clean up ##########