示例#1
0
    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)

        conn_params = pg.get_conn_params(m_ansible_module, m_ansible_module.params)
        db_connection = pg.connect_to_db(m_ansible_module, conn_params, 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)

        conn_params = pg.get_conn_params(m_ansible_module, m_ansible_module.params)
        db_connection = pg.connect_to_db(m_ansible_module, conn_params, 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
示例#2
0
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)
示例#4
0
def main():
    argument_spec = postgres_common_argument_spec()
    argument_spec.update(
        groups=dict(type='list', elements='str', required=True, aliases=['group', 'source_role', 'source_roles']),
        target_roles=dict(type='list', elements='str', required=True, 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)
示例#5
0
    def connect(self):
        """Connect to a PostgreSQL database and return a cursor object.

        Note: connection parameters are passed by self.module object.
        """
        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)
示例#6
0
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', elements='str'),
        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,
    )
示例#7
0
    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)

        conn_params = pg.get_conn_params(m_ansible_module, m_ansible_module.params)
        db_connection = pg.connect_to_db(m_ansible_module, conn_params)
        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
示例#8
0
    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

        conn_params = pg.get_conn_params(m_ansible_module, m_ansible_module.params)
        db_connection = pg.connect_to_db(m_ansible_module, conn_params, fail_on_conn=True)

        assert 'unable to connect to database' in m_ansible_module.err_msg
        assert db_connection is None
示例#9
0
    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

        conn_params = pg.get_conn_params(m_ansible_module, m_ansible_module.params)
        db_connection = pg.connect_to_db(m_ansible_module, conn_params, 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
示例#10
0
def main():
    argument_spec = postgres_common_argument_spec()
    argument_spec.update(
        db=dict(type="str", aliases=["login_db"]),
        name=dict(type="str", required=True, 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")

    # When slot_type is logical and parameter db is not passed,
    # the default database will be used to create the slot and
    # the user should know about this.
    # When the slot type is physical,
    # it doesn't matter which database will be used
    # because physical slots are global objects.
    if slot_type == 'logical':
        warn_db_default = True
    else:
        warn_db_default = False

    conn_params = get_conn_params(module, module.params, warn_db_default=warn_db_default)
    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(
        query=dict(type='str'),
        db=dict(type='str', aliases=['login_db']),
        positional_args=dict(type='list', elements='raw'),
        named_args=dict(type='dict'),
        session_role=dict(type='str'),
        path_to_script=dict(type='path'),
        autocommit=dict(type='bool', default=False),
        encoding=dict(type='str'),
        trust_input=dict(type='bool', default=True),
        search_path=dict(type='list', elements='str'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=(('positional_args', 'named_args'), ),
        supports_check_mode=True,
    )

    query = module.params["query"]
    positional_args = module.params["positional_args"]
    named_args = module.params["named_args"]
    path_to_script = module.params["path_to_script"]
    autocommit = module.params["autocommit"]
    encoding = module.params["encoding"]
    session_role = module.params["session_role"]
    trust_input = module.params["trust_input"]
    search_path = module.params["search_path"]

    if not trust_input:
        # Check input for potentially dangerous elements:
        check_input(module, session_role)

    if autocommit and module.check_mode:
        module.fail_json(
            msg="Using autocommit is mutually exclusive with check_mode")

    if path_to_script and query:
        module.fail_json(msg="path_to_script is mutually exclusive with query")

    if positional_args:
        positional_args = convert_elements_to_pg_arrays(positional_args)

    elif named_args:
        named_args = convert_elements_to_pg_arrays(named_args)

    query_list = []
    if path_to_script:
        try:
            with open(path_to_script, 'rb') as f:
                query = to_native(f.read())
                if ';' in query:
                    query_list = [q for q in query.split(';') if q != '\n']
                else:
                    query_list.append(query)
        except Exception as e:
            module.fail_json(msg="Cannot read file '%s' : %s" %
                             (path_to_script, to_native(e)))
    else:
        query_list.append(query)

    conn_params = get_conn_params(module, module.params)
    db_connection = connect_to_db(module, conn_params, autocommit=autocommit)
    if encoding is not None:
        db_connection.set_client_encoding(encoding)
    cursor = db_connection.cursor(cursor_factory=DictCursor)

    if search_path:
        set_search_path(cursor,
                        '%s' % ','.join([x.strip(' ') for x in search_path]))

    # Prepare args:
    if module.params.get("positional_args"):
        arguments = module.params["positional_args"]
    elif module.params.get("named_args"):
        arguments = module.params["named_args"]
    else:
        arguments = None

    # Set defaults:
    changed = False

    query_all_results = []
    rowcount = 0
    statusmessage = ''

    # Execute query:
    for query in query_list:
        try:
            cursor.execute(query, arguments)
            statusmessage = cursor.statusmessage
            if cursor.rowcount > 0:
                rowcount += cursor.rowcount

            try:
                query_result = [dict(row) for row in cursor.fetchall()]

            except Psycopg2ProgrammingError as e:
                if to_native(e) == 'no results to fetch':
                    query_result = {}

            except Exception as e:
                module.fail_json(msg="Cannot fetch rows from cursor: %s" %
                                 to_native(e))

            query_all_results.append(query_result)

            if 'SELECT' not in statusmessage:
                if 'UPDATE' in statusmessage or 'INSERT' in statusmessage or 'DELETE' in statusmessage:
                    s = statusmessage.split()
                    if len(s) == 3:
                        if s[2] != '0':
                            changed = True

                    elif len(s) == 2:
                        if s[1] != '0':
                            changed = True

                    else:
                        changed = True

                else:
                    changed = True

        except Exception as e:
            if not autocommit:
                db_connection.rollback()

            cursor.close()
            db_connection.close()
            module.fail_json(
                msg="Cannot execute SQL '%s' %s: %s, query list: %s" %
                (query, arguments, to_native(e), query_list))

    if module.check_mode:
        db_connection.rollback()
    else:
        if not autocommit:
            db_connection.commit()

    kw = dict(
        changed=changed,
        query=cursor.query,
        query_list=query_list,
        statusmessage=statusmessage,
        query_result=query_result,
        query_all_results=query_all_results,
        rowcount=rowcount,
    )

    cursor.close()
    db_connection.close()

    module.exit_json(**kw)
示例#12
0
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', default=False),
        schema=dict(type='str', default='public'),
        cascade=dict(type='bool', default=False),
        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:
    conn_params = get_conn_params(module, module.params)
    db_connection = connect_to_db(module, conn_params, 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(
        name=dict(required=True),
        db=dict(type='str', aliases=['login_db']),
        state=dict(type='str', default='present', choices=['absent', 'present']),
        tables=dict(type='list', elements='str'),
        parameters=dict(type='dict'),
        owner=dict(type='str'),
        cascade=dict(type='bool', default=False),
        session_role=dict(type='str'),
        trust_input=dict(type='bool', default=True),
    )
    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']
    session_role = module.params['session_role']
    trust_input = module.params['trust_input']

    if not trust_input:
        # Check input for potentially dangerous elements:
        if not params:
            params_list = None
        else:
            params_list = ['%s = %s' % (k, v) for k, v in iteritems(params)]

        check_input(module, name, tables, owner, session_role, params_list)

    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.warn('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 == 'present' 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)
示例#14
0
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"),
                         owner=dict(type="str"),
                         trust_input=dict(type="bool", default="yes"))

    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"]
    owner = module.params["owner"]
    session_role = module.params["session_role"]
    trust_input = module.params["trust_input"]

    if not trust_input:
        # Check input for potentially dangerous elements:
        check_input(module, lang, session_role, owner)

    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 owner and state == 'present':
        if lang_exists(cursor, lang):
            if owner != get_lang_owner(cursor, lang):
                changed = set_lang_owner(cursor, lang, owner)

    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)
示例#15
0
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', no_log=False),
        expires=dict(type='str', default=None),
        conn_limit=dict(type='int', default=None),
        session_role=dict(type='str'),
        groups=dict(type='list', elements='str'),
        comment=dict(type='str', default=None),
        trust_input=dict(type='bool', default=True),
    )
    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]
    comment = module.params["comment"]
    session_role = module.params['session_role']

    trust_input = module.params['trust_input']
    if not trust_input:
        # Check input for potentially dangerous elements:
        check_input(module, user, password, privs, expires,
                    role_attr_flags, groups, comment, session_role)

    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, groups, target_roles)
            changed = pg_membership.grant() or changed
            executed_queries.extend(pg_membership.executed_queries)

        if comment is not None:
            try:
                changed = add_comment(cursor, user, comment) or changed
            except Exception as e:
                module.fail_json(msg='Unable to add comment on role: %s' % to_native(e),
                                 exception=traceback.format_exc())

    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(
        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),
        unique=dict(type='bool', default=False),
        table=dict(type='str'),
        idxtype=dict(type='str', aliases=['type']),
        columns=dict(type='list', elements='str', aliases=['column']),
        cond=dict(type='str'),
        session_role=dict(type='str'),
        tablespace=dict(type='str'),
        storage_params=dict(type='list', elements='str'),
        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 == '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, 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(
        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']),
        publications=dict(type='list', elements='str'),
        connparams=dict(type='dict'),
        cascade=dict(type='bool', default=False),
        owner=dict(type='str'),
        subsparams=dict(type='dict'),
        session_role=dict(type='str'),
        trust_input=dict(type='bool', default=True),
    )
    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']
    session_role = module.params['session_role']
    trust_input = module.params['trust_input']

    if not trust_input:
        # Check input for potentially dangerous elements:
        if not subsparams:
            subsparams_str = None
        else:
            subsparams_str = convert_subscr_params(subsparams)

        if not connparams:
            connparams_str = None
        else:
            connparams_str = convert_conn_params(connparams)

        check_input(module, name, publications, owner, session_role,
                    connparams_str, subsparams_str)

    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)

    if subscription.exists:
        initial_state = deepcopy(subscription.attrs)
        final_state = deepcopy(initial_state)

    if 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:
    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(
        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(
        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"),
        trust_input=dict(type="bool", default=True),
    )

    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"]
    session_role = module.params["session_role"]
    trust_input = module.params["trust_input"]

    if not trust_input:
        # Check input for potentially dangerous elements:
        check_input(module, schema, owner, session_role)

    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)
示例#20
0
def main():
    argument_spec = postgres_common_argument_spec()
    argument_spec.update(
        tablespace=dict(type='str', required=True, 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)
示例#21
0
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'),
        trust_input=dict(type='bool', default=True),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    name = module.params['name']
    value = module.params['value']
    reset = module.params['reset']
    session_role = module.params['session_role']
    trust_input = module.params['trust_input']

    if not trust_input:
        # Check input for potentially dangerous elements:
        check_input(module, name, value, session_role)

    # Allow to pass values like 1mb instead of 1MB, etc:
    if value:
        for unit in POSSIBLE_SIZE_UNITS:
            if value[:-2].isdigit() and unit in value[-2:]:
                value = value.upper()

    if value is not None and reset:
        module.fail_json(msg="%s: value and reset params are mutually exclusive" % name)

    if value is None 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 (value can be an empty string):
    if value is not None 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)

    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

    if restart_required and changed:
        module.warn("Restart of PostgreSQL is required for setting %s" % name)

    module.exit_json(**kw)
示例#22
0
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', elements='str'),
        storage_params=dict(type='list', elements='str'),
        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 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', elements='str', 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,
    )