def test_autocommit_true(self, m_ansible_module, monkeypatch, m_psycopg2): """ Test connect_to_db(), autocommit arg passed as True (the default is False). """ monkeypatch.setattr(pg, 'HAS_PSYCOPG2', True) # case 1: psycopg2.__version >= 2.4.2 (the default in m_psycopg2) monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) db_connection = pg.connect_to_db(m_ansible_module, autocommit=True) cursor = db_connection.cursor() # if errors, db_connection returned as None: assert isinstance(db_connection, DbConnection) assert isinstance(cursor, Cursor) assert m_ansible_module.err_msg == '' # case 2: psycopg2.__version < 2.4.2 m_psycopg2.__version__ = '2.4.1' monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) db_connection = pg.connect_to_db(m_ansible_module, autocommit=True) cursor = db_connection.cursor() # if errors, db_connection returned as None: assert isinstance(db_connection, DbConnection) assert isinstance(cursor, Cursor) assert 'psycopg2 must be at least 2.4.3' in m_ansible_module.err_msg
def connect(self): try: self.db_conn = connect_to_db(self.module, warn_db_default=False) self.cursor = self.db_conn.cursor(cursor_factory=DictCursor) # Switch role, if specified: if self.session_role: try: self.cursor.execute('SET ROLE %s' % self.session_role) except Exception as e: self.module.fail_json(msg="Could not switch role: %s" % to_native(e)) return self.cursor except TypeError as e: if 'sslrootcert' in e.args[0]: self.module.fail_json( msg='PostgreSQL server must be at least version 8.4 ' 'to support sslrootcert') self.module.fail_json(msg="Unable to connect to database: %s" % to_native(e)) except Exception as e: self.module.fail_json(msg="Unable to connect to database: %s" % to_native(e))
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( groups=dict(type='list', aliases=['group', 'source_role', 'source_roles']), target_roles=dict(type='list', aliases=['target_role', 'user', 'users']), fail_on_role=dict(type='bool', default=True), state=dict(type='str', default='present', choices=['absent', 'present']), db=dict(type='str', aliases=['login_db']), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) groups = module.params['groups'] target_roles = module.params['target_roles'] fail_on_role = module.params['fail_on_role'] state = module.params['state'] conn_params = get_conn_params(module, module.params, warn_db_default=False) db_connection = connect_to_db(module, conn_params, autocommit=False) cursor = db_connection.cursor(cursor_factory=DictCursor) ############## # Create the object and do main job: pg_membership = PgMembership(module, cursor, groups, target_roles, fail_on_role) if state == 'present': pg_membership.grant() elif state == 'absent': pg_membership.revoke() # Rollback if it's possible and check_mode: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() # Make return values: return_dict = dict( changed=pg_membership.changed, state=state, groups=pg_membership.groups, target_roles=pg_membership.target_roles, queries=pg_membership.executed_queries, ) if state == 'present': return_dict['granted'] = pg_membership.granted elif state == 'absent': return_dict['revoked'] = pg_membership.revoked module.exit_json(**return_dict)
def connect(self): """Connect to a PostgreSQL database and return a cursor object. Note: connection parameters are passed by self.module object. """ self.db_conn = connect_to_db(self.module, warn_db_default=False) return self.db_conn.cursor(cursor_factory=DictCursor)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update(db=dict(type='str', aliases=['login_db']), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) # Set some default values: cursor = False db_connection = False result = dict( changed=False, is_available=False, server_version=dict(), ) conn_params = get_conn_params(module, module.params, warn_db_default=False) db_connection = connect_to_db(module, conn_params, fail_on_conn=False) if db_connection is not None: cursor = db_connection.cursor(cursor_factory=DictCursor) # Do job: pg_ping = PgPing(module, cursor) if cursor: # If connection established: result["is_available"], result["server_version"] = pg_ping.do() db_connection.rollback() module.exit_json(**result)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type='str', aliases=['login_db']), filter=dict(type='list', elements='str'), session_role=dict(type='str'), schema=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) filter_ = module.params["filter"] schema = module.params["schema"] # Connect to DB and make cursor object: pg_conn_params = get_conn_params(module, module.params) # We don't need to commit anything, so, set it to False: db_connection = connect_to_db(module, pg_conn_params, autocommit=False) cursor = db_connection.cursor(cursor_factory=DictCursor) ############################ # Create object and do work: pg_obj_info = PgUserObjStatInfo(module, cursor) info_dict = pg_obj_info.collect(filter_, schema) # Clean up: cursor.close() db_connection.close() # Return information: module.exit_json(**info_dict)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( new_owner=dict(type='str', required=True), obj_name=dict(type='str'), obj_type=dict(type='str', aliases=['type'], choices=[ 'database', 'function', 'matview', 'sequence', 'schema', 'table', 'tablespace', 'view']), reassign_owned_by=dict(type='list'), fail_on_role=dict(type='bool', default=True), db=dict(type='str', aliases=['login_db']), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=[ ['obj_name', 'reassign_owned_by'], ['obj_type', 'reassign_owned_by'], ['obj_name', 'fail_on_role'], ['obj_type', 'fail_on_role'], ], supports_check_mode=True, ) new_owner = module.params['new_owner'] obj_name = module.params['obj_name'] obj_type = module.params['obj_type'] reassign_owned_by = module.params['reassign_owned_by'] fail_on_role = module.params['fail_on_role'] conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=False) cursor = db_connection.cursor(cursor_factory=DictCursor) ############## # Create the object and do main job: pg_ownership = PgOwnership(module, cursor, new_owner) # if we want to change ownership: if obj_name: pg_ownership.set_owner(obj_type, obj_name) # if we want to reassign objects owned by roles: elif reassign_owned_by: pg_ownership.reassign(reassign_owned_by, fail_on_role) # Rollback if it's possible and check_mode: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() module.exit_json( changed=pg_ownership.changed, queries=pg_ownership.executed_queries, )
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", aliases=["login_db"]), name=dict(type="str", aliases=["slot_name"]), slot_type=dict(type="str", default="physical", choices=["logical", "physical"]), immediately_reserve=dict(type="bool", default=False), session_role=dict(type="str"), output_plugin=dict(type="str", default="test_decoding"), state=dict(type="str", default="present", choices=["absent", "present"]), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) name = module.params["name"] slot_type = module.params["slot_type"] immediately_reserve = module.params["immediately_reserve"] state = module.params["state"] output_plugin = module.params["output_plugin"] if immediately_reserve and slot_type == 'logical': module.fail_json(msg="Module parameters immediately_reserve and slot_type=logical are mutually exclusive") conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) ################################## # Create an object and do main job pg_slot = PgSlot(module, cursor, name) changed = False if module.check_mode: if state == "present": if not pg_slot.exists: changed = True pg_slot.create(slot_type, immediately_reserve, output_plugin, just_check=True) elif state == "absent": if pg_slot.exists: changed = True else: if state == "absent": pg_slot.drop() elif state == "present": pg_slot.create(slot_type, immediately_reserve, output_plugin) changed = pg_slot.changed db_connection.close() module.exit_json(changed=changed, name=name, queries=pg_slot.executed_queries)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( schema=dict(type="str", required=True, aliases=['name']), owner=dict(type="str", default=""), database=dict(type="str", default="postgres", aliases=["db", "login_db"]), cascade_drop=dict(type="bool", default=False), state=dict(type="str", default="present", choices=["absent", "present"]), session_role=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) schema = module.params["schema"] owner = module.params["owner"] state = module.params["state"] cascade_drop = module.params["cascade_drop"] changed = False conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) try: if module.check_mode: if state == "absent": changed = not schema_exists(cursor, schema) elif state == "present": changed = not schema_matches(cursor, schema, owner) module.exit_json(changed=changed, schema=schema) if state == "absent": try: changed = schema_delete(cursor, schema, cascade_drop) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) elif state == "present": try: changed = schema_create(cursor, schema, owner) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) except NotSupportedError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) except SystemExit: # Avoid catching this on Python 2.4 raise except Exception as e: module.fail_json(msg="Database query failed: %s" % to_native(e), exception=traceback.format_exc()) db_connection.close() module.exit_json(changed=changed, schema=schema, queries=executed_queries)
def test_fail_on_conn_true(self, m_ansible_module, monkeypatch, m_psycopg2): """ Test connect_to_db(), fail_on_conn arg passed as True (the default behavior). """ monkeypatch.setattr(pg, 'HAS_PSYCOPG2', True) monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) m_ansible_module.params['login_user'] = '******' # causes Exception db_connection = pg.connect_to_db(m_ansible_module, fail_on_conn=True) assert 'unable to connect to database' in m_ansible_module.err_msg assert db_connection is None
def test_connect_to_db(self, m_ansible_module, monkeypatch, m_psycopg2): """Test connect_to_db(), common test.""" monkeypatch.setattr(pg, 'HAS_PSYCOPG2', True) monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) db_connection = pg.connect_to_db(m_ansible_module) cursor = db_connection.cursor() # if errors, db_connection returned as None: assert isinstance(db_connection, DbConnection) assert isinstance(cursor, Cursor) assert m_ansible_module.err_msg == '' # The default behaviour, normal in this case: assert 'Database name has not been passed' in m_ansible_module.warn_msg
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", required=True, aliases=["login_db"]), ext=dict(type="str", required=True, aliases=["name"]), schema=dict(type="str"), state=dict(type="str", default="present", choices=["absent", "present"]), cascade=dict(type="bool", default=False), session_role=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) ext = module.params["ext"] schema = module.params["schema"] state = module.params["state"] cascade = module.params["cascade"] changed = False conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) try: if module.check_mode: if state == "present": changed = not ext_exists(cursor, ext) elif state == "absent": changed = ext_exists(cursor, ext) else: if state == "absent": changed = ext_delete(cursor, ext, cascade) elif state == "present": changed = ext_create(cursor, ext, schema, cascade) except Exception as e: db_connection.close() module.fail_json(msg="Database query failed: %s" % to_native(e), exception=traceback.format_exc()) db_connection.close() module.exit_json(changed=changed, db=module.params["db"], ext=ext, queries=executed_queries)
def test_warn_db_default_non_default(self, m_ansible_module, monkeypatch, m_psycopg2): """ Test connect_to_db(), warn_db_default arg passed as False (by default is True). """ monkeypatch.setattr(pg, 'HAS_PSYCOPG2', True) monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) db_connection = pg.connect_to_db(m_ansible_module, warn_db_default=False) cursor = db_connection.cursor() # if errors, db_connection returned as None: assert isinstance(db_connection, DbConnection) assert isinstance(cursor, Cursor) assert m_ansible_module.err_msg == '' assert m_ansible_module.warn_msg == ''
def test_fail_on_conn_false(self, m_ansible_module, monkeypatch, m_psycopg2): """ Test connect_to_db(), fail_on_conn arg passed as False. """ monkeypatch.setattr(pg, 'HAS_PSYCOPG2', True) monkeypatch.setattr(pg, 'psycopg2', m_psycopg2) m_ansible_module.params['login_user'] = '******' # causes Exception db_connection = pg.connect_to_db(m_ansible_module, fail_on_conn=False) assert m_ansible_module.err_msg == '' assert 'PostgreSQL server is unavailable' in m_ansible_module.warn_msg assert db_connection is None
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( name=dict(type='str', required=True), db=dict(type='str', aliases=['login_db']), value=dict(type='str'), reset=dict(type='bool'), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) name = module.params["name"] value = module.params["value"] reset = module.params["reset"] # Allow to pass values like 1mb instead of 1MB, etc: if value: for unit in POSSIBLE_SIZE_UNITS: if unit in value: value = value.upper() if value and reset: module.fail_json(msg="%s: value and reset params are mutually exclusive" % name) if not value and not reset: module.fail_json(msg="%s: at least one of value or reset param must be specified" % name) conn_params = get_conn_params(module, module.params, warn_db_default=False) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) kw = {} # Check server version (needs 9.4 or later): ver = db_connection.server_version if ver < PG_REQ_VER: module.warn("PostgreSQL is %s version but %s or later is required" % (ver, PG_REQ_VER)) kw = dict( changed=False, restart_required=False, value_pretty="", prev_val_pretty="", value={"value": "", "unit": ""}, ) kw['name'] = name db_connection.close() module.exit_json(**kw) # Set default returned values: restart_required = False changed = False kw['name'] = name kw['restart_required'] = False # Get info about param state: res = param_get(cursor, module, name) current_value = res[0] raw_val = res[1] unit = res[2] boot_val = res[3] context = res[4] if value == 'True': value = 'on' elif value == 'False': value = 'off' kw['prev_val_pretty'] = current_value kw['value_pretty'] = deepcopy(kw['prev_val_pretty']) kw['context'] = context # Do job if context == "internal": module.fail_json(msg="%s: cannot be changed (internal context). See " "https://www.postgresql.org/docs/current/runtime-config-preset.html" % name) if context == "postmaster": restart_required = True # If check_mode, just compare and exit: if module.check_mode: if pretty_to_bytes(value) == pretty_to_bytes(current_value): kw['changed'] = False else: kw['value_pretty'] = value kw['changed'] = True # Anyway returns current raw value in the check_mode: kw['value'] = dict( value=raw_val, unit=unit, ) kw['restart_required'] = restart_required module.exit_json(**kw) # Set param: if value and value != current_value: changed = param_set(cursor, module, name, value, context) kw['value_pretty'] = value # Reset param: elif reset: if raw_val == boot_val: # nothing to change, exit: kw['value'] = dict( value=raw_val, unit=unit, ) module.exit_json(**kw) changed = param_set(cursor, module, name, boot_val, context) if restart_required: module.warn("Restart of PostgreSQL is required for setting %s" % name) cursor.close() db_connection.close() # Reconnect and recheck current value: if context in ('sighup', 'superuser-backend', 'backend', 'superuser', 'user'): db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) res = param_get(cursor, module, name) # f_ means 'final' f_value = res[0] f_raw_val = res[1] if raw_val == f_raw_val: changed = False else: changed = True kw['value_pretty'] = f_value kw['value'] = dict( value=f_raw_val, unit=unit, ) cursor.close() db_connection.close() kw['changed'] = changed kw['restart_required'] = restart_required module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", required=True, aliases=["login_db"]), lang=dict(type="str", required=True, aliases=["name"]), state=dict(type="str", default="present", choices=["absent", "present"]), trust=dict(type="bool", default="no"), force_trust=dict(type="bool", default="no"), cascade=dict(type="bool", default="no"), fail_on_drop=dict(type="bool", default="yes"), session_role=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) db = module.params["db"] lang = module.params["lang"] state = module.params["state"] trust = module.params["trust"] force_trust = module.params["force_trust"] cascade = module.params["cascade"] fail_on_drop = module.params["fail_on_drop"] conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=False) cursor = db_connection.cursor() changed = False kw = {'db': db, 'lang': lang, 'trust': trust} if state == "present": if lang_exists(cursor, lang): lang_trusted = lang_istrusted(cursor, lang) if (lang_trusted and not trust) or (not lang_trusted and trust): if module.check_mode: changed = True else: changed = lang_altertrust(cursor, lang, trust) else: if module.check_mode: changed = True else: changed = lang_add(cursor, lang, trust) if force_trust: changed = lang_altertrust(cursor, lang, trust) else: if lang_exists(cursor, lang): if module.check_mode: changed = True kw['lang_dropped'] = True else: changed = lang_drop(cursor, lang, cascade) if fail_on_drop and not changed: msg = "unable to drop language, use cascade to delete dependencies or fail_on_drop=no to ignore" module.fail_json(msg=msg) kw['lang_dropped'] = changed if changed: if module.check_mode: db_connection.rollback() else: db_connection.commit() kw['changed'] = changed kw['queries'] = executed_queries db_connection.close() module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() 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', 'stat']), concurrent=dict(type='bool', default=True), unique=dict(type='bool', default=False), table=dict(type='str'), idxtype=dict(type='str', aliases=['type']), columns=dict(type='list', aliases=['column']), cond=dict(type='str'), session_role=dict(type='str'), tablespace=dict(type='str'), storage_params=dict(type='list'), cascade=dict(type='bool', default=False), schema=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) idxname = module.params["idxname"] state = module.params["state"] concurrent = module.params["concurrent"] unique = module.params["unique"] table = module.params["table"] idxtype = module.params["idxtype"] columns = module.params["columns"] cond = module.params["cond"] tablespace = module.params["tablespace"] storage_params = module.params["storage_params"] cascade = module.params["cascade"] schema = module.params["schema"] if concurrent and cascade: module.fail_json( msg="Concurrent mode and cascade parameters are mutually exclusive" ) if unique and (idxtype and idxtype != 'btree'): module.fail_json(msg="Only btree currently supports unique indexes") if state == 'present': if not table: module.fail_json(msg="Table must be specified") if not columns: module.fail_json(msg="At least one column must be specified") else: if table or columns or cond or idxtype or tablespace: module.fail_json( msg="Index %s is going to be removed, so it does not " "make sense to pass a table name, columns, conditions, " "index type, or tablespace" % idxname) if cascade and state != 'absent': module.fail_json(msg="cascade parameter used only with state=absent") conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) # Set defaults: changed = False # Do job: index = Index(module, cursor, schema, idxname) kw = index.get_info() kw['query'] = '' # # check_mode start if module.check_mode: 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) elif state == 'present' and not index.exists: kw['changed'] = True module.exit_json(**kw) elif state == 'absent' and not index.exists: kw['changed'] = False module.exit_json(**kw) elif state == 'absent' and index.exists: kw['changed'] = True module.exit_json(**kw) # check_mode end # 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)) columns = ','.join(columns) if storage_params: storage_params = ','.join(storage_params) changed = index.create(table, idxtype, columns, cond, tablespace, storage_params, concurrent, unique) if changed: kw = index.get_info() kw['state'] = 'present' kw['query'] = index.executed_query else: changed = index.drop(schema, cascade, concurrent) if changed: kw['state'] = 'absent' kw['query'] = index.executed_query if not kw['valid']: db_connection.rollback() module.warn("Index %s is invalid! ROLLBACK" % idxname) if not concurrent: db_connection.commit() kw['changed'] = changed db_connection.close() module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( tablespace=dict(type='str', aliases=['name']), state=dict(type='str', default="present", choices=["absent", "present"]), location=dict(type='path', aliases=['path']), owner=dict(type='str'), set=dict(type='dict'), rename_to=dict(type='str'), db=dict(type='str', aliases=['login_db']), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=(('positional_args', 'named_args'), ), supports_check_mode=True, ) tablespace = module.params["tablespace"] state = module.params["state"] location = module.params["location"] owner = module.params["owner"] rename_to = module.params["rename_to"] settings = module.params["set"] if state == 'absent' and (location or owner or rename_to or settings): module.fail_json(msg="state=absent is mutually exclusive location, " "owner, rename_to, and set") conn_params = get_conn_params(module, module.params, warn_db_default=False) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) # Change autocommit to False if check_mode: if module.check_mode: if PSYCOPG2_VERSION >= '2.4.2': db_connection.set_session(autocommit=False) else: db_connection.set_isolation_level(READ_COMMITTED) # Set defaults: autocommit = False changed = False ############## # Create PgTablespace object and do main job: tblspace = PgTablespace(module, cursor, tablespace) # If tablespace exists with different location, exit: if tblspace.exists and location and location != tblspace.location: module.fail_json( msg="Tablespace '%s' exists with different location '%s'" % (tblspace.name, tblspace.location)) # Create new tablespace: if not tblspace.exists and state == 'present': if rename_to: module.fail_json( msg="Tablespace %s does not exist, nothing to rename" % tablespace) if not location: module.fail_json(msg="'location' parameter must be passed with " "state=present if the tablespace doesn't exist") # Because CREATE TABLESPACE can not be run inside the transaction block: autocommit = True if PSYCOPG2_VERSION >= '2.4.2': db_connection.set_session(autocommit=True) else: db_connection.set_isolation_level(AUTOCOMMIT) changed = tblspace.create(location) # Drop non-existing tablespace: elif not tblspace.exists and state == 'absent': # Nothing to do: module.fail_json(msg="Tries to drop nonexistent tablespace '%s'" % tblspace.name) # Drop existing tablespace: elif tblspace.exists and state == 'absent': # Because DROP TABLESPACE can not be run inside the transaction block: autocommit = True if PSYCOPG2_VERSION >= '2.4.2': db_connection.set_session(autocommit=True) else: db_connection.set_isolation_level(AUTOCOMMIT) changed = tblspace.drop() # Rename tablespace: elif tblspace.exists and rename_to: if tblspace.name != rename_to: changed = tblspace.rename(rename_to) if state == 'present': # Refresh information: tblspace.get_info() # Change owner and settings: if state == 'present' and tblspace.exists: if owner: changed = tblspace.set_owner(owner) if settings: changed = tblspace.set_settings(settings) tblspace.get_info() # Rollback if it's possible and check_mode: if not autocommit: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() # Make return values: kw = dict( changed=changed, state='present', tablespace=tblspace.name, owner=tblspace.owner, queries=tblspace.executed_queries, options=tblspace.settings, location=tblspace.location, ) if state == 'present': kw['state'] = 'present' if tblspace.new_name: kw['newname'] = tblspace.new_name elif state == 'absent': kw['state'] = 'absent' module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( name=dict(type='str', required=True), db=dict(type='str', aliases=['login_db']), value=dict(type='str'), reset=dict(type='bool'), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) if not HAS_PSYCOPG2: module.fail_json(msg=missing_required_lib('psycopg2')) name = module.params["name"] value = module.params["value"] reset = module.params["reset"] sslrootcert = module.params["ca_cert"] session_role = module.params["session_role"] # Allow to pass values like 1mb instead of 1MB, etc: if value: for unit in POSSIBLE_SIZE_UNITS: if unit in value: value = value.upper() if value and reset: module.fail_json( msg="%s: value and reset params are mutually exclusive" % name) if not value and not reset: module.fail_json( msg="%s: at least one of value or reset param must be specified" % name) # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw # dictionary params_map = { "login_host": "host", "login_user": "******", "login_password": "******", "port": "port", "db": "database", "ssl_mode": "sslmode", "ca_cert": "sslrootcert" } kw = dict((params_map[k], v) for (k, v) in iteritems(module.params) if k in params_map and v != '' and v is not None) # Store connection parameters for the final check: con_params = deepcopy(kw) # If a login_unix_socket is specified, incorporate it here. is_localhost = "host" not in kw or kw["host"] is None or kw[ "host"] == "localhost" if is_localhost and module.params["login_unix_socket"] != "": kw["host"] = module.params["login_unix_socket"] if psycopg2.__version__ < '2.4.3' and sslrootcert: module.fail_json(msg='psycopg2 must be at least 2.4.3 ' 'in order to user the ca_cert parameter') db_connection = connect_to_db(module, kw, autocommit=True) cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor) # Check server version (needs 9.4 or later): ver = get_pg_version(cursor) if ver < PG_REQ_VER: module.warn("PostgreSQL is %s version but %s or later is required" % (ver, PG_REQ_VER)) kw = dict( changed=False, restart_required=False, value_pretty="", prev_val_pretty="", value={ "value": "", "unit": "" }, ) kw['name'] = name db_connection.close() module.exit_json(**kw) # Switch role, if specified: if session_role: try: cursor.execute('SET ROLE %s' % session_role) except Exception as e: module.fail_json(msg="Could not switch role: %s" % to_native(e)) # Set default returned values: restart_required = False changed = False kw['name'] = name kw['restart_required'] = False # Get info about param state: res = param_get(cursor, module, name) current_value = res[0] raw_val = res[1] unit = res[2] boot_val = res[3] context = res[4] if value == 'True': value = 'on' elif value == 'False': value = 'off' kw['prev_val_pretty'] = current_value kw['value_pretty'] = deepcopy(kw['prev_val_pretty']) kw['context'] = context # Do job if context == "internal": module.fail_json( msg="%s: cannot be changed (internal context). See " "https://www.postgresql.org/docs/current/runtime-config-preset.html" % name) if context == "postmaster": restart_required = True # If check_mode, just compare and exit: if module.check_mode: if pretty_to_bytes(value) == pretty_to_bytes(current_value): kw['changed'] = False else: kw['value_pretty'] = value kw['changed'] = True # Anyway returns current raw value in the check_mode: kw['value'] = dict( value=raw_val, unit=unit, ) kw['restart_required'] = restart_required module.exit_json(**kw) # Set param: if value and value != current_value: changed = param_set(cursor, module, name, value, context) kw['value_pretty'] = value # Reset param: elif reset: if raw_val == boot_val: # nothing to change, exit: kw['value'] = dict( value=raw_val, unit=unit, ) module.exit_json(**kw) changed = param_set(cursor, module, name, boot_val, context) if restart_required: module.warn("Restart of PostgreSQL is required for setting %s" % name) cursor.close() db_connection.close() # Reconnect and recheck current value: if context in ('sighup', 'superuser-backend', 'backend', 'superuser', 'user'): db_connection = connect_to_db(module, con_params, autocommit=True) cursor = db_connection.cursor( cursor_factory=psycopg2.extras.DictCursor) res = param_get(cursor, module, name) # f_ means 'final' f_value = res[0] f_raw_val = res[1] if raw_val == f_raw_val: changed = False else: changed = True kw['value_pretty'] = f_value kw['value'] = dict( value=f_raw_val, unit=unit, ) cursor.close() db_connection.close() kw['changed'] = changed kw['restart_required'] = restart_required module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( copy_to=dict(type='path', aliases=['to']), copy_from=dict(type='path', aliases=['from']), src=dict(type='str', aliases=['source']), dst=dict(type='str', aliases=['destination']), columns=dict(type='list', aliases=['column']), options=dict(type='dict'), program=dict(type='bool', default=False), db=dict(type='str', aliases=['login_db']), session_role=dict(type='str'), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[ ['copy_from', 'copy_to'], ['copy_from', 'src'], ['copy_to', 'dst'], ]) # Note: we don't need to check mutually exclusive params here, because they are # checked automatically by AnsibleModule (mutually_exclusive=[] list above). if module.params.get('copy_from') and not module.params.get('dst'): module.fail_json(msg='dst param is necessary with copy_from') elif module.params.get('copy_to') and not module.params.get('src'): module.fail_json(msg='src param is necessary with copy_to') # Connect to DB and make cursor object: conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=False) cursor = db_connection.cursor(cursor_factory=DictCursor) ############## # Create the object and do main job: data = PgCopyData(module, cursor) # Note: parameters like dst, src, etc. are got # from module object into data object of PgCopyData class. # Therefore not need to pass args to the methods below. # Note: check mode is implemented inside the methods below # by checking passed module.check_mode arg. if module.params.get('copy_to'): data.copy_to() elif module.params.get('copy_from'): data.copy_from() # Finish: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() # Return some values: module.exit_json( changed=data.changed, queries=data.executed_queries, src=data.src, dst=data.dst, )
def main(): argument_spec = postgres_common_argument_spec() 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']), concurrent=dict(type='bool', default=True), table=dict(type='str'), idxtype=dict(type='str', aliases=['type']), columns=dict(type='list', aliases=['column']), cond=dict(type='str'), session_role=dict(type='str'), tablespace=dict(type='str'), storage_params=dict(type='list'), cascade=dict(type='bool', default=False), schema=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) if not HAS_PSYCOPG2: module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) idxname = module.params["idxname"] state = module.params["state"] concurrent = module.params["concurrent"] table = module.params["table"] idxtype = module.params["idxtype"] columns = module.params["columns"] cond = module.params["cond"] sslrootcert = module.params["ca_cert"] session_role = module.params["session_role"] tablespace = module.params["tablespace"] storage_params = module.params["storage_params"] cascade = module.params["cascade"] schema = module.params["schema"] if concurrent and cascade: module.fail_json( msg="Cuncurrent mode and cascade parameters are mutually exclusive" ) if state == 'present': if not table: module.fail_json(msg="Table must be specified") if not columns: module.fail_json(msg="At least one column must be specified") else: if table or columns or cond or idxtype or tablespace: module.fail_json( msg="Index %s is going to be removed, so it does not " "make sense to pass a table name, columns, conditions, " "index type, or tablespace" % idxname) if cascade and state != 'absent': module.fail_json(msg="cascade parameter used only with state=absent") # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw # dictionary params_map = { "login_host": "host", "login_user": "******", "login_password": "******", "port": "port", "db": "database", "ssl_mode": "sslmode", "ca_cert": "sslrootcert" } kw = dict((params_map[k], v) for (k, v) in iteritems(module.params) if k in params_map and v != "" and v is not None) # If a login_unix_socket is specified, incorporate it here. is_localhost = "host" not in kw or kw["host"] is None or kw[ "host"] == "localhost" if is_localhost and module.params["login_unix_socket"] != "": kw["host"] = module.params["login_unix_socket"] if psycopg2.__version__ < '2.4.3' and sslrootcert is not None: module.fail_json( msg= 'psycopg2 must be at least 2.4.3 in order to user the ca_cert parameter' ) db_connection = connect_to_db(module, kw, autocommit=True) cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor) if session_role: try: cursor.execute('SET ROLE %s' % session_role) except Exception as e: module.fail_json(msg="Could not switch role: %s" % to_native(e)) # Set defaults: changed = False # Do job: index = Index(module, cursor, schema, idxname) kw = index.get_info() kw['query'] = '' # # check_mode start if module.check_mode: if state == 'present' and index.exists: kw['changed'] = False module.exit_json(**kw) elif state == 'present' and not index.exists: kw['changed'] = True module.exit_json(**kw) elif state == 'absent' and not index.exists: kw['changed'] = False module.exit_json(**kw) elif state == 'absent' and index.exists: kw['changed'] = True module.exit_json(**kw) # check_mode end # if 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)) columns = ','.join(columns) if storage_params: storage_params = ','.join(storage_params) changed = index.create(table, idxtype, columns, cond, tablespace, storage_params, concurrent) if changed: kw = index.get_info() kw['state'] = 'present' kw['query'] = index.executed_query else: changed = index.drop(schema, cascade, concurrent) if changed: kw['state'] = 'absent' kw['query'] = index.executed_query if not kw['valid']: db_connection.rollback() module.warn("Index %s is invalid! ROLLBACK" % idxname) if not concurrent: db_connection.commit() kw['changed'] = changed module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( db=dict(type="str", required=True, aliases=["login_db"]), ext=dict(type="str", required=True, aliases=["name"]), schema=dict(type="str"), state=dict(type="str", default="present", choices=["absent", "present"]), cascade=dict(type="bool", default=False), session_role=dict(type="str"), version=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) ext = module.params["ext"] schema = module.params["schema"] state = module.params["state"] cascade = module.params["cascade"] version = module.params["version"] changed = False if version and state == 'absent': module.warn("Parameter version is ignored when state=absent") conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) try: # Get extension info and available versions: curr_version, available_versions = ext_get_versions(cursor, ext) if state == "present": if version == 'latest': if available_versions: version = available_versions[-1] else: version = '' if version: # If the specific version is passed and it is not available for update: if version not in available_versions: if not curr_version: module.fail_json( msg="Passed version '%s' is not available" % version) elif LooseVersion(curr_version) == LooseVersion(version): changed = False else: module.fail_json( msg="Passed version '%s' is lower than " "the current created version '%s' or " "the passed version is not available" % (version, curr_version)) # If the specific version is passed and it is higher that the current version: if curr_version and version: if LooseVersion(curr_version) < LooseVersion(version): if module.check_mode: changed = True else: changed = ext_update_version(cursor, ext, version) # If the specific version is passed and it is created now: if curr_version == version: changed = False # If the ext doesn't exist and installed: elif not curr_version and available_versions: if module.check_mode: changed = True else: changed = ext_create(cursor, ext, schema, cascade, version) # If version is not passed: else: if not curr_version: # If the ext doesn't exist and it's installed: if available_versions: if module.check_mode: changed = True else: changed = ext_create(cursor, ext, schema, cascade, version) # If the ext doesn't exist and not installed: else: module.fail_json(msg="Extension %s is not installed" % ext) elif state == "absent": if curr_version: if module.check_mode: changed = True else: changed = ext_delete(cursor, ext, cascade) else: changed = False except Exception as e: db_connection.close() module.fail_json(msg="Database query failed: %s" % to_native(e), exception=traceback.format_exc()) db_connection.close() module.exit_json(changed=changed, db=module.params["db"], ext=ext, queries=executed_queries)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( sequence=dict(type='str', required=True, aliases=['name']), state=dict(type='str', default='present', choices=['absent', 'present']), data_type=dict(type='str', choices=['bigint', 'integer', 'smallint']), increment=dict(type='int'), minvalue=dict(type='int', aliases=['min']), maxvalue=dict(type='int', aliases=['max']), start=dict(type='int'), cache=dict(type='int'), cycle=dict(type='bool'), schema=dict(type='str', default='public'), cascade=dict(type='bool'), rename_to=dict(type='str'), owner=dict(type='str'), newschema=dict(type='str'), db=dict(type='str', default='', aliases=['login_db', 'database']), session_role=dict(type='str'), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=[ ['rename_to', 'data_type'], ['rename_to', 'increment'], ['rename_to', 'minvalue'], ['rename_to', 'maxvalue'], ['rename_to', 'start'], ['rename_to', 'cache'], ['rename_to', 'cycle'], ['rename_to', 'cascade'], ['rename_to', 'owner'], ['rename_to', 'newschema'], ['cascade', 'data_type'], ['cascade', 'increment'], ['cascade', 'minvalue'], ['cascade', 'maxvalue'], ['cascade', 'start'], ['cascade', 'cache'], ['cascade', 'cycle'], ['cascade', 'owner'], ['cascade', 'newschema'], ]) # Note: we don't need to check mutually exclusive params here, because they are # checked automatically by AnsibleModule (mutually_exclusive=[] list above). # Change autocommit to False if check_mode: autocommit = not module.check_mode # Connect to DB and make cursor object: db_connection = connect_to_db(module, autocommit=autocommit) cursor = db_connection.cursor(cursor_factory=DictCursor) ############## # Create the object and do main job: data = Sequence(module, cursor) # Set defaults: changed = False # Create new sequence if not data.exists and module.params['state'] == 'present': if module.params.get('rename_to'): module.fail_json( msg="Sequence '%s' does not exist, nothing to rename" % module.params['sequence']) if module.params.get('newschema'): module.fail_json( msg= "Sequence '%s' does not exist, change of schema not possible" % module.params['sequence']) changed = data.create() # Drop non-existing sequence elif not data.exists and module.params['state'] == 'absent': # Nothing to do changed = False # Drop existing sequence elif data.exists and module.params['state'] == 'absent': changed = data.drop() # Rename sequence if data.exists and module.params.get('rename_to'): if data.name != module.params['rename_to']: changed = data.rename() if changed: data.new_name = module.params['rename_to'] # Refresh information if module.params['state'] == 'present': data.get_info() # Change owner, schema and settings if module.params['state'] == 'present' and data.exists: # change owner if module.params.get('owner'): if data.owner != module.params['owner']: changed = data.set_owner() # Set schema if module.params.get('newschema'): if data.schema != module.params['newschema']: changed = data.set_schema() if changed: data.new_schema = module.params['newschema'] # Rollback if it's possible and check_mode: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() # Make return values: kw = dict( changed=changed, state='present', sequence=data.name, queries=data.executed_queries, schema=data.schema, data_type=data.data_type, increment=data.increment, minvalue=data.minvalue, maxvalue=data.maxvalue, start=data.start_value, cycle=data.cycle, owner=data.owner, ) if module.params['state'] == 'present': if data.new_name: kw['newname'] = data.new_name if data.new_schema: kw['newschema'] = data.new_schema elif module.params['state'] == 'absent': kw['state'] = 'absent' module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( new_owner=dict(type='str', required=True), obj_name=dict(type='str'), obj_type=dict(type='str', aliases=['type'], choices=[ 'database', 'function', 'matview', 'sequence', 'schema', 'table', 'tablespace', 'view']), reassign_owned_by=dict(type='list'), fail_on_role=dict(type='bool', default=True), db=dict(type='str', aliases=['login_db']), session_role=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, mutually_exclusive=[ ['obj_name', 'reassign_owned_by'], ['obj_type', 'reassign_owned_by'], ['obj_name', 'fail_on_role'], ['obj_type', 'fail_on_role'], ], supports_check_mode=True, ) if not HAS_PSYCOPG2: module.fail_json(msg=missing_required_lib('psycopg2')) new_owner = module.params['new_owner'] obj_name = module.params['obj_name'] obj_type = module.params['obj_type'] reassign_owned_by = module.params['reassign_owned_by'] fail_on_role = module.params['fail_on_role'] sslrootcert = module.params['ca_cert'] session_role = module.params['session_role'] # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw # dictionary params_map = { "login_host": "host", "login_user": "******", "login_password": "******", "port": "port", "db": "database", "ssl_mode": "sslmode", "ca_cert": "sslrootcert" } kw = dict((params_map[k], v) for (k, v) in iteritems(module.params) if k in params_map and v != '' and v is not None) # If a login_unix_socket is specified, incorporate it here. is_localhost = "host" not in kw or kw["host"] is None or kw["host"] == "localhost" if is_localhost and module.params["login_unix_socket"] != "": kw["host"] = module.params["login_unix_socket"] if psycopg2.__version__ < '2.4.3' and sslrootcert: module.fail_json(msg='psycopg2 must be at least 2.4.3 ' 'in order to user the ssl_rootcert parameter') db_connection = connect_to_db(module, kw, autocommit=False) cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor) # Switch role, if specified: if session_role: try: cursor.execute('SET ROLE %s' % session_role) except Exception as e: module.fail_json(msg="Could not switch role: %s" % to_native(e)) ############## # Create the object and do main job: pg_ownership = PgOwnership(module, cursor, new_owner) # if we want to change ownership: if obj_name: pg_ownership.set_owner(obj_type, obj_name) # if we want to reassign objects owned by roles: elif reassign_owned_by: pg_ownership.reassign(reassign_owned_by, fail_on_role) # Rollback if it's possible and check_mode: if module.check_mode: db_connection.rollback() else: db_connection.commit() cursor.close() db_connection.close() module.exit_json( changed=pg_ownership.changed, queries=pg_ownership.executed_queries, )
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( name=dict(required=True), db=dict(type='str', aliases=['login_db']), state=dict(type='str', default='present', choices=['absent', 'present']), tables=dict(type='list'), parameters=dict(type='dict'), owner=dict(type='str'), cascade=dict(type='bool', default=False), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) # Parameters handling: name = module.params['name'] state = module.params['state'] tables = module.params['tables'] params = module.params['parameters'] owner = module.params['owner'] cascade = module.params['cascade'] if state == 'absent': if tables: module.warn('parameter "tables" is ignored when "state=absent"') if params: module.warn( 'parameter "parameters" is ignored when "state=absent"') if owner: module.warn('parameter "owner" is ignored when "state=absent"') if state == 'present' and cascade: module.warm('parameter "cascade" is ignored when "state=present"') # Connect to DB and make cursor object: conn_params = get_conn_params(module, module.params) # We check publication state without DML queries execution, so set autocommit: db_connection = connect_to_db(module, conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) # Check version: if cursor.connection.server_version < SUPPORTED_PG_VERSION: module.fail_json( msg="PostgreSQL server version should be 10.0 or greater") # Nothing was changed by default: changed = False ################################### # Create object and do rock'n'roll: publication = PgPublication(module, cursor, name) if tables: tables = transform_tables_representation(tables) # If module.check_mode=True, nothing will be changed: if state == 'present': if not publication.exists: changed = publication.create(tables, params, owner, check_mode=module.check_mode) else: changed = publication.update(tables, params, owner, check_mode=module.check_mode) elif state == 'absent': changed = publication.drop(cascade=cascade, check_mode=module.check_mode) # Get final publication info: pub_fin_info = {} if state != 'absent' or (state == 'absent' and module.check_mode): pub_fin_info = publication.get_info() elif state == 'absent' and not module.check_mode: publication.exists = False # Connection is not needed any more: cursor.close() db_connection.close() # Update publication info and return ret values: module.exit_json(changed=changed, queries=publication.executed_queries, exists=publication.exists, **pub_fin_info)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( user=dict(type='str', required=True, aliases=['name']), password=dict(type='str', default=None, no_log=True), state=dict(type='str', default='present', choices=['absent', 'present']), priv=dict(type='str', default=None), db=dict(type='str', default='', aliases=['login_db']), fail_on_user=dict(type='bool', default='yes', aliases=['fail_on_role']), role_attr_flags=dict(type='str', default=''), encrypted=dict(type='bool', default='yes'), no_password_changes=dict(type='bool', default='no'), expires=dict(type='str', default=None), conn_limit=dict(type='int', default=None), session_role=dict(type='str'), groups=dict(type='list'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True ) user = module.params["user"] password = module.params["password"] state = module.params["state"] fail_on_user = module.params["fail_on_user"] if module.params['db'] == '' and module.params["priv"] is not None: module.fail_json(msg="privileges require a database to be specified") privs = parse_privs(module.params["priv"], module.params["db"]) no_password_changes = module.params["no_password_changes"] if module.params["encrypted"]: encrypted = "ENCRYPTED" else: encrypted = "UNENCRYPTED" expires = module.params["expires"] conn_limit = module.params["conn_limit"] role_attr_flags = module.params["role_attr_flags"] groups = module.params["groups"] if groups: groups = [e.strip() for e in groups] conn_params = get_conn_params(module, module.params, warn_db_default=False) db_connection = connect_to_db(module, conn_params) cursor = db_connection.cursor(cursor_factory=DictCursor) try: role_attr_flags = parse_role_attrs(cursor, role_attr_flags) except InvalidFlagsError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) kw = dict(user=user) changed = False user_removed = False if state == "present": if user_exists(cursor, user): try: changed = user_alter(db_connection, module, user, password, role_attr_flags, encrypted, expires, no_password_changes, conn_limit) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) else: try: changed = user_add(cursor, user, password, role_attr_flags, encrypted, expires, conn_limit) except psycopg2.ProgrammingError as e: module.fail_json(msg="Unable to add user with given requirement " "due to : %s" % to_native(e), exception=traceback.format_exc()) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) try: changed = grant_privileges(cursor, user, privs) or changed except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) if groups: target_roles = [] target_roles.append(user) pg_membership = PgMembership(module, cursor, target_roles, groups) changed = pg_membership.grant() else: if user_exists(cursor, user): if module.check_mode: changed = True kw['user_removed'] = True else: try: changed = revoke_privileges(cursor, user, privs) user_removed = user_delete(cursor, user) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) changed = changed or user_removed if fail_on_user and not user_removed: msg = "Unable to remove user" module.fail_json(msg=msg) kw['user_removed'] = user_removed if changed: if module.check_mode: db_connection.rollback() else: db_connection.commit() kw['changed'] = changed kw['queries'] = executed_queries module.exit_json(**kw)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( name=dict(required=True), db=dict(type='str', aliases=['login_db']), state=dict(type='str', default='present', choices=['absent', 'present', 'refresh', 'stat']), publications=dict(type='list'), 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, supports_check_mode=True, ) # Parameters handling: db = module.params['db'] name = module.params['name'] state = module.params['state'] publications = module.params['publications'] cascade = module.params['cascade'] 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') if state != 'present': if owner: module.warn( "parameter 'owner' is ignored when state is not 'present'") if publications: module.warn( "parameter 'publications' is ignored when state is not 'present'" ) if connparams: module.warn( "parameter 'connparams' is ignored when state is not 'present'" ) if subsparams: module.warn( "parameter 'subsparams' is ignored when state is not 'present'" ) # Connect to DB and make cursor object: pg_conn_params = get_conn_params(module, module.params) # We check subscription state without DML queries execution, so set autocommit: db_connection = connect_to_db(module, pg_conn_params, autocommit=True) cursor = db_connection.cursor(cursor_factory=DictCursor) # Check version: if cursor.connection.server_version < SUPPORTED_PG_VERSION: module.fail_json( msg="PostgreSQL server version should be 10.0 or greater") # Set defaults: changed = False initial_state = {} final_state = {} ################################### # Create object and do rock'n'roll: subscription = PgSubscription(module, cursor, name, db, relinfo) 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 not subscription.exists: if subsparams: subsparams = convert_subscr_params(subsparams) if connparams: connparams = convert_conn_params(connparams) changed = subscription.create(connparams, publications, subsparams, check_mode=module.check_mode) else: changed = subscription.update(connparams, publications, subsparams, check_mode=module.check_mode) if owner and subscription.attrs['owner'] != owner: changed = subscription.set_owner( owner, check_mode=module.check_mode) or changed elif state == 'absent': changed = subscription.drop(cascade, check_mode=module.check_mode) elif state == 'refresh': if not subscription.exists: module.fail_json( msg="Refresh failed: subscription '%s' does not exist" % name) # 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() # Connection is not needed any more: cursor.close() db_connection.close() # Return ret values and exit: module.exit_json(changed=changed, name=name, exists=subscription.exists, queries=subscription.executed_queries, initial_state=initial_state, final_state=final_state)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( schema=dict(type="str", required=True, aliases=['name']), owner=dict(type="str", default=""), database=dict(type="str", default="postgres", aliases=["db", "login_db"]), cascade_drop=dict(type="bool", default=False), state=dict(type="str", default="present", choices=["absent", "present"]), session_role=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) if not HAS_PSYCOPG2: module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) schema = module.params["schema"] owner = module.params["owner"] state = module.params["state"] sslrootcert = module.params["ca_cert"] cascade_drop = module.params["cascade_drop"] session_role = module.params["session_role"] changed = False # To use defaults values, keyword arguments must be absent, so # check which values are empty and don't include in the **kw # dictionary params_map = { "login_host": "host", "login_user": "******", "login_password": "******", "port": "port", "database": "database", "ssl_mode": "sslmode", "ca_cert": "sslrootcert" } kw = dict((params_map[k], v) for (k, v) in iteritems(module.params) if k in params_map and v != "" and v is not None) # If a login_unix_socket is specified, incorporate it here. is_localhost = "host" not in kw or kw["host"] == "" or kw[ "host"] == "localhost" if is_localhost and module.params["login_unix_socket"] != "": kw["host"] = module.params["login_unix_socket"] if psycopg2.__version__ < '2.4.3' and sslrootcert is not None: module.fail_json( msg= 'psycopg2 must be at least 2.4.3 in order to user the ca_cert parameter' ) db_connection = connect_to_db(module, kw, autocommit=True) cursor = db_connection.cursor(cursor_factory=psycopg2.extras.DictCursor) if session_role: try: cursor.execute('SET ROLE %s' % pg_quote_identifier(session_role, 'role')) except Exception as e: module.fail_json(msg="Could not switch role: %s" % to_native(e), exception=traceback.format_exc()) try: if module.check_mode: if state == "absent": changed = not schema_exists(cursor, schema) elif state == "present": changed = not schema_matches(cursor, schema, owner) module.exit_json(changed=changed, schema=schema) if state == "absent": try: changed = schema_delete(cursor, schema, cascade_drop) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) elif state == "present": try: changed = schema_create(cursor, schema, owner) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) except NotSupportedError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) except SystemExit: # Avoid catching this on Python 2.4 raise except Exception as e: module.fail_json(msg="Database query failed: %s" % to_native(e), exception=traceback.format_exc()) module.exit_json(changed=changed, schema=schema, queries=executed_queries)
def main(): argument_spec = postgres_common_argument_spec() argument_spec.update( table=dict(type='str', required=True, aliases=['name']), state=dict(type='str', default="present", choices=["absent", "present"]), db=dict(type='str', default='', aliases=['login_db']), tablespace=dict(type='str'), owner=dict(type='str'), unlogged=dict(type='bool', default=False), like=dict(type='str'), including=dict(type='str'), rename=dict(type='str'), truncate=dict(type='bool', default=False), columns=dict(type='list'), storage_params=dict(type='list'), session_role=dict(type='str'), cascade=dict(type='bool', default=False), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) table = module.params["table"] state = module.params["state"] tablespace = module.params["tablespace"] owner = module.params["owner"] unlogged = module.params["unlogged"] like = module.params["like"] including = module.params["including"] newname = module.params["rename"] storage_params = module.params["storage_params"] truncate = module.params["truncate"] columns = module.params["columns"] cascade = module.params["cascade"] if state == 'present' and cascade: 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): module.fail_json(msg="%s: state=absent is mutually exclusive with: " "truncate, rename, columns, tablespace, " "including, like, storage_params, unlogged, owner" % table) if truncate and (newname or columns or like or unlogged or storage_params or owner or tablespace or including): module.fail_json(msg="%s: truncate is mutually exclusive with: " "rename, columns, like, unlogged, including, " "storage_params, owner, tablespace" % table) if newname and (columns or like or unlogged or storage_params or owner or tablespace or including): module.fail_json(msg="%s: rename is mutually exclusive with: " "columns, like, unlogged, including, " "storage_params, owner, tablespace" % table) if like and columns: module.fail_json(msg="%s: like and columns params are mutually exclusive" % table) if including and not like: module.fail_json(msg="%s: including param needs like param specified" % table) conn_params = get_conn_params(module, module.params) db_connection = connect_to_db(module, conn_params, autocommit=False) cursor = db_connection.cursor(cursor_factory=DictCursor) if storage_params: storage_params = ','.join(storage_params) if columns: columns = ','.join(columns) ############## # Do main job: table_obj = Table(table, module, cursor) # Set default returned values: changed = False kw = {} kw['table'] = table kw['state'] = '' if table_obj.exists: kw = dict( table=table, state='present', owner=table_obj.info['owner'], tablespace=table_obj.info['tblspace'], storage_params=table_obj.info['storage_params'], ) if state == 'absent': changed = table_obj.drop(cascade=cascade) elif truncate: changed = table_obj.truncate() elif newname: changed = table_obj.rename(newname) q = table_obj.executed_queries table_obj = Table(newname, module, cursor) table_obj.executed_queries = q elif state == 'present' and not like: changed = table_obj.create(columns, storage_params, tablespace, unlogged, owner) elif state == 'present' and like: changed = table_obj.create_like(like, including, tablespace, unlogged, storage_params) if changed: if module.check_mode: db_connection.rollback() else: db_connection.commit() # Refresh table info for RETURN. # Note, if table has been renamed, it gets info by newname: table_obj.get_info() db_connection.commit() if table_obj.exists: kw = dict( table=table, state='present', owner=table_obj.info['owner'], tablespace=table_obj.info['tblspace'], storage_params=table_obj.info['storage_params'], ) else: # We just change the table state here # to keep other information about the dropped table: kw['state'] = 'absent' kw['queries'] = table_obj.executed_queries kw['changed'] = changed db_connection.close() module.exit_json(**kw)
def connect(self): conn_params = get_conn_params(self.module, self.module.params, warn_db_default=False) self.db_conn = connect_to_db(self.module, conn_params) return self.db_conn.cursor(cursor_factory=DictCursor)