postgresql_user: fix doc formatting, added return value, aliases, misc code changes (#54768)

* postgresql_user: refactoring

* postgresql_user: removed line from ignore.txt

* postgresql_user: removed lines from ignore.txt

* postgresql_user: removed lines from ignore.txt, fixes

* postgresql_user: removed lines from ignore.txt, fixes

* postgresql_user: removed lines from ignore.txt, fixes
pull/54899/head
Andrey Klychkov 6 years ago committed by John R Barker
parent d16452bc8f
commit 3eff72e886

@ -24,6 +24,8 @@ options:
- Name of the extension to add or remove. - Name of the extension to add or remove.
required: true required: true
type: str type: str
aliases:
- ext
db: db:
description: description:
- Name of the database to add or remove the extension to/from. - Name of the database to add or remove the extension to/from.
@ -40,6 +42,7 @@ options:
description: description:
- The username used to authenticate with. - The username used to authenticate with.
type: str type: str
default: postgres
login_password: login_password:
description: description:
- The password used to authenticate with. - The password used to authenticate with.
@ -48,7 +51,6 @@ options:
description: description:
- Host running the database. - Host running the database.
type: str type: str
default: localhost
login_unix_socket: login_unix_socket:
description: description:
- Path to a Unix domain socket for local connections. - Path to a Unix domain socket for local connections.
@ -70,7 +72,7 @@ options:
- Specifies the name of a file containing SSL certificate authority (CA) - Specifies the name of a file containing SSL certificate authority (CA)
certificate(s). If the file exists, the server's certificate will be certificate(s). If the file exists, the server's certificate will be
verified to be signed by one of these authorities. verified to be signed by one of these authorities.
type: path type: str
version_added: '2.8' version_added: '2.8'
aliases: [ ssl_rootcert ] aliases: [ ssl_rootcert ]
port: port:
@ -78,6 +80,8 @@ options:
- Database port to connect to. - Database port to connect to.
default: 5432 default: 5432
type: int type: int
aliases:
- login_port
session_role: session_role:
description: description:
- Switch to session_role after connecting. - Switch to session_role after connecting.
@ -219,14 +223,10 @@ def main():
argument_spec = postgres_common_argument_spec() argument_spec = postgres_common_argument_spec()
argument_spec.update( argument_spec.update(
db=dict(type="str", required=True, aliases=["login_db"]), db=dict(type="str", required=True, aliases=["login_db"]),
port=dict(type="int", default=5432, aliases=["login_port"]), ext=dict(type="str", required=True, aliases=["name"]),
ext=dict(type="str", required=True, aliases=['name']),
schema=dict(type="str"), schema=dict(type="str"),
state=dict(type="str", default="present", choices=["absent", "present"]), state=dict(type="str", default="present", choices=["absent", "present"]),
cascade=dict(type='bool', default=False), cascade=dict(type="bool", default=False),
ssl_mode=dict(type='str', default='prefer', choices=[
'disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']),
ca_cert=dict(type="path", default=None, aliases=['ssl_rootcert']),
session_role=dict(type="str"), session_role=dict(type="str"),
) )

@ -93,7 +93,6 @@ options:
description: description:
- Host running PostgreSQL where you want to execute the actions. - Host running PostgreSQL where you want to execute the actions.
type: str type: str
default: localhost
session_role: session_role:
version_added: '2.8' version_added: '2.8'
description: description:
@ -267,16 +266,12 @@ def main():
argument_spec = postgres_common_argument_spec() argument_spec = postgres_common_argument_spec()
argument_spec.update( argument_spec.update(
db=dict(type="str", required=True, aliases=["login_db"]), db=dict(type="str", required=True, aliases=["login_db"]),
port=dict(type="int", default=5432, aliases=["login_port"]),
lang=dict(type="str", required=True, aliases=["name"]), lang=dict(type="str", required=True, aliases=["name"]),
state=dict(type="str", default="present", choices=["absent", "present"]), state=dict(type="str", default="present", choices=["absent", "present"]),
trust=dict(type="bool", default="no"), trust=dict(type="bool", default="no"),
force_trust=dict(type="bool", default="no"), force_trust=dict(type="bool", default="no"),
cascade=dict(type="bool", default="no"), cascade=dict(type="bool", default="no"),
fail_on_drop=dict(type="bool", default="yes"), fail_on_drop=dict(type="bool", default="yes"),
ssl_mode=dict(default='prefer', choices=[
'allow', 'disable', 'prefer', 'require', 'verify-ca', 'verify-full']),
ca_cert=dict(default=None, aliases=["ssl_rootcert"]),
session_role=dict(type="str"), session_role=dict(type="str"),
) )

@ -24,6 +24,8 @@ options:
- Name of the schema to add or remove. - Name of the schema to add or remove.
required: true required: true
type: str type: str
aliases:
- schema
database: database:
description: description:
- Name of the database to connect to and add or remove the schema. - Name of the database to connect to and add or remove the schema.
@ -36,6 +38,7 @@ options:
description: description:
- The username used to authenticate with. - The username used to authenticate with.
type: str type: str
default: postgres
login_password: login_password:
description: description:
- The password used to authenticate with. - The password used to authenticate with.
@ -44,7 +47,6 @@ options:
description: description:
- Host running the database. - Host running the database.
type: str type: str
default: localhost
login_unix_socket: login_unix_socket:
description: description:
- Path to a Unix domain socket for local connections. - Path to a Unix domain socket for local connections.

@ -1,208 +1,235 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright: Ansible Project # Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
ANSIBLE_METADATA = { ANSIBLE_METADATA = {
'metadata_version': '1.1', 'metadata_version': '1.1',
'status': ['stableinterface'], 'status': ['stableinterface'],
'supported_by': 'community' 'supported_by': 'community'
} }
DOCUMENTATION = r'''
DOCUMENTATION = '''
--- ---
module: postgresql_user module: postgresql_user
short_description: Adds or removes a user (role) from a remote PostgreSQL server instance. short_description: Add or remove a user (role) from a PostgreSQL server instance
description: description:
- Adds or removes a user (role) from a remote PostgreSQL server instance - Adds or removes a user (role) from a PostgreSQL server instance
("cluster" in PostgreSQL terminology) and, optionally, ("cluster" in PostgreSQL terminology) and, optionally,
grants the user access to an existing database or tables. grants the user access to an existing database or tables.
A user is a role with login privilege (see U(https://www.postgresql.org/docs/11/role-attributes.html) for more information). A user is a role with login privilege
- The fundamental function of the module is to create, or delete, users from (see U(https://www.postgresql.org/docs/11/role-attributes.html) for more information).
a PostgreSQL instances. Privilege assignment, or removal, is an optional - The fundamental function of the module is to create, or delete, users from
step, which works on one database at a time. This allows for the module to a PostgreSQL instances. Privilege assignment, or removal, is an optional
be called several times in the same module to modify the permissions on step, which works on one database at a time. This allows for the module to
different databases, or to grant permissions to already existing users. be called several times in the same module to modify the permissions on
- A user cannot be removed until all the privileges have been stripped from different databases, or to grant permissions to already existing users.
the user. In such situation, if the module tries to remove the user it - A user cannot be removed until all the privileges have been stripped from
will fail. To avoid this from happening the fail_on_user option signals the user. In such situation, if the module tries to remove the user it
the module to try to remove the user, but if not possible keep going; the will fail. To avoid this from happening the fail_on_user option signals
module will report if changes happened and separately if the user was the module to try to remove the user, but if not possible keep going; the
removed or not. module will report if changes happened and separately if the user was
version_added: "0.6" removed or not.
version_added: '0.6'
options: options:
name: name:
description: description:
- Name of the user (role) to add or remove. - Name of the user (role) to add or remove.
type: str
required: true required: true
aliases:
- user
password: password:
description: description:
- Set the user's password, before 1.4 this was required. - Set the user's password, before 1.4 this was required.
- Password can be passed unhashed or hashed (MD5-hashed). - Password can be passed unhashed or hashed (MD5-hashed).
- Unhashed password will automatically be hashed when saved into the - Unhashed password will automatically be hashed when saved into the
database if C(encrypted) parameter is set, otherwise it will be save in database if C(encrypted) parameter is set, otherwise it will be save in
plain text format. plain text format.
- When passing a hashed password it must be generated with the format - When passing a hashed password it must be generated with the format
C('str["md5"] + md5[ password + username ]'), resulting in a total of C('str["md5"] + md5[ password + username ]'), resulting in a total of
35 characters. An easy way to do this is C(echo "md5$(echo -n 35 characters. An easy way to do this is C(echo "md5$(echo -n
'verysecretpasswordJOE' | md5sum | awk '{print $1}')"). 'verysecretpasswordJOE' | md5sum | awk '{print $1}')").
- Note that if the provided password string is already in MD5-hashed - Note that if the provided password string is already in MD5-hashed
format, then it is used as-is, regardless of C(encrypted) parameter. format, then it is used as-is, regardless of C(encrypted) parameter.
type: str
db: db:
description: description:
- Name of database to connect to and where user's permissions will be granted. - Name of database to connect to and where user's permissions will be granted.
type: str
aliases:
- login_db
fail_on_user: fail_on_user:
description: description:
- If C(yes), fail when user (role) can't be removed. Otherwise just log and - If C(yes), fail when user (role) can't be removed. Otherwise just log and continue.
continue.
default: 'yes' default: 'yes'
type: bool type: bool
aliases:
- fail_on_role
port: port:
description: description:
- Database port to connect to. - Database port to connect to.
type: int
default: 5432 default: 5432
aliases:
- login_port
login_user: login_user:
description: description:
- User (role) used to authenticate with PostgreSQL. - User (role) used to authenticate with PostgreSQL.
type: str
default: postgres default: postgres
login_password: login_password:
description: description:
- Password used to authenticate with PostgreSQL. - Password for U(login_user) used to authenticate with PostgreSQL.
type: str
login_host: login_host:
description: description:
- Host running PostgreSQL. - Host running PostgreSQL.
default: localhost type: str
login_unix_socket: login_unix_socket:
description: description:
- Path to a Unix domain socket for local connections. - Path to a Unix domain socket for local connections.
type: str
priv: priv:
description: description:
- "Slash-separated PostgreSQL privileges string: C(priv1/priv2), where - "Slash-separated PostgreSQL privileges string: C(priv1/priv2), where
privileges can be defined for database ( allowed options - 'CREATE', privileges can be defined for database ( allowed options - 'CREATE',
'CONNECT', 'TEMPORARY', 'TEMP', 'ALL'. For example C(CONNECT) ) or 'CONNECT', 'TEMPORARY', 'TEMP', 'ALL'. For example C(CONNECT) ) or
for table ( allowed options - 'SELECT', 'INSERT', 'UPDATE', 'DELETE', for table ( allowed options - 'SELECT', 'INSERT', 'UPDATE', 'DELETE',
'TRUNCATE', 'REFERENCES', 'TRIGGER', 'ALL'. For example 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'ALL'. For example
C(table:SELECT) ). Mixed example of this string: C(table:SELECT) ). Mixed example of this string:
C(CONNECT/CREATE/table1:SELECT/table2:INSERT)." C(CONNECT/CREATE/table1:SELECT/table2:INSERT)."
type: str
role_attr_flags: role_attr_flags:
description: description:
- "PostgreSQL user attributes string in the format: CREATEDB,CREATEROLE,SUPERUSER." - "PostgreSQL user attributes string in the format: CREATEDB,CREATEROLE,SUPERUSER."
- Note that '[NO]CREATEUSER' is deprecated. - Note that '[NO]CREATEUSER' is deprecated.
choices: ["[NO]SUPERUSER", "[NO]CREATEROLE", "[NO]CREATEDB", "[NO]INHERIT", "[NO]LOGIN", "[NO]REPLICATION", "[NO]BYPASSRLS"] - To create a simple role for using it like a group, use C(NOLOGIN) flag.
type: str
choices: [ '[NO]SUPERUSER', '[NO]CREATEROLE', '[NO]CREATEDB',
'[NO]INHERIT', '[NO]LOGIN', '[NO]REPLICATION', '[NO]BYPASSRLS' ]
session_role: session_role:
version_added: "2.8" version_added: '2.8'
description: | description:
Switch to session_role after connecting. The specified session_role must be a role that the current login_user is a member of. - Switch to session_role after connecting.
Permissions checking for SQL commands is carried out as though the session_role were the one that had logged in originally. - The specified session_role must be a role that the current login_user is a member of.
- Permissions checking for SQL commands is carried out as though the session_role were the one that had logged in originally.
type: str
state: state:
description: description:
- The user (role) state. - The user (role) state.
type: str
default: present default: present
choices: ["present", "absent"] choices: [ absent, present ]
encrypted: encrypted:
description: description:
- Whether the password is stored hashed in the database. Passwords can be - Whether the password is stored hashed in the database.
passed already hashed or unhashed, and postgresql ensures the stored - Passwords can be passed already hashed or unhashed, and postgresql
password is hashed when C(encrypted) is set. ensures the stored password is hashed when C(encrypted) is set.
- "Note: Postgresql 10 and newer doesn't support unhashed passwords." - "Note: Postgresql 10 and newer doesn't support unhashed passwords."
- Previous to Ansible 2.6, this was C(no) by default. - Previous to Ansible 2.6, this was C(no) by default.
default: 'yes' default: 'yes'
type: bool type: bool
version_added: '1.4' version_added: '1.4'
expires: expires:
description: description:
- The date at which the user's password is to expire. - The date at which the user's password is to expire.
- If set to C('infinity'), user's password never expire. - If set to C('infinity'), user's password never expire.
- Note that this value should be a valid SQL date and time type. - Note that this value should be a valid SQL date and time type.
type: str
version_added: '1.4' version_added: '1.4'
no_password_changes: no_password_changes:
description: description:
- If C(yes), don't inspect database for password changes. Effective when - If C(yes), don't inspect database for password changes. Effective when
C(pg_authid) is not accessible (such as AWS RDS). Otherwise, make C(pg_authid) is not accessible (such as AWS RDS). Otherwise, make
password changes as necessary. password changes as necessary.
default: 'no' default: 'no'
type: bool type: bool
version_added: '2.0' version_added: '2.0'
ssl_mode: ssl_mode:
description: description:
- Determines whether or with what priority a secure SSL TCP/IP connection - Determines whether or with what priority a secure SSL TCP/IP connection
will be negotiated with the server. will be negotiated with the server.
- See U(https://www.postgresql.org/docs/current/static/libpq-ssl.html) for - See U(https://www.postgresql.org/docs/current/static/libpq-ssl.html) for
more information on the modes. more information on the modes.
- Default of C(prefer) matches libpq default. - Default of C(prefer) matches libpq default.
default: prefer default: prefer
choices: ["disable", "allow", "prefer", "require", "verify-ca", "verify-full"] choices: [ allow, disable, prefer, require, verify-ca, verify-full ]
version_added: '2.3' version_added: '2.3'
ca_cert: ca_cert:
description: description:
- Specifies the name of a file containing SSL certificate authority (CA) - Specifies the name of a file containing SSL certificate authority (CA)
certificate(s). If the file exists, the server's certificate will be certificate(s). If the file exists, the server's certificate will be
verified to be signed by one of these authorities. verified to be signed by one of these authorities.
type: str
version_added: '2.3' version_added: '2.3'
aliases: [ ssl_rootcert ] aliases: [ ssl_rootcert ]
conn_limit: conn_limit:
description: description:
- Specifies the user (role) connection limit. - Specifies the user (role) connection limit.
version_added: '2.4'
type: int type: int
version_added: '2.4'
notes: notes:
- The module creates a user (role) with login privilege by default. - The module creates a user (role) with login privilege by default.
Use NOLOGIN role_attr_flags to change this behaviour. Use NOLOGIN role_attr_flags to change this behaviour.
- The default authentication assumes that you are either logging in as or - The default authentication assumes that you are either logging in as or
sudo'ing to the postgres account on the host. sudo'ing to the postgres account on the host.
- This module uses psycopg2, a Python PostgreSQL database adapter. You must - This module uses psycopg2, a Python PostgreSQL database adapter. You must
ensure that psycopg2 is installed on the host before using this module. If ensure that psycopg2 is installed on the host before using this module. If
the remote host is the PostgreSQL server (which is the default case), then the remote host is the PostgreSQL server (which is the default case), then
PostgreSQL must also be installed on the remote host. For Ubuntu-based PostgreSQL must also be installed on the remote host. For Ubuntu-based
systems, install the postgresql, libpq-dev, and python-psycopg2 packages systems, install the postgresql, libpq-dev, and python-psycopg2 packages
on the remote host before using this module. on the remote host before using this module.
- If you specify PUBLIC as the user (role), then the privilege changes will apply - If you specify PUBLIC as the user (role), then the privilege changes will apply to all users (roles).
to all users (roles). You may not specify password or role_attr_flags when the You may not specify password or role_attr_flags when the PUBLIC user is specified.
PUBLIC user is specified. - The ca_cert parameter requires at least Postgres version 8.4 and I(psycopg2) version 2.4.3.
- The ca_cert parameter requires at least Postgres version 8.4 and
I(psycopg2) version 2.4.3. requirements:
requirements: [ psycopg2 ] - psycopg2
author: "Ansible Core Team"
author:
- Ansible Core Team
''' '''
EXAMPLES = ''' EXAMPLES = r'''
# Connect to acme database, create django user, and grant access to database and products table - name: Connect to acme database, create django user, and grant access to database and products table
- postgresql_user: postgresql_user:
db: acme db: acme
name: django name: django
password: ceec4eif7ya password: ceec4eif7ya
priv: "CONNECT/products:ALL" priv: "CONNECT/products:ALL"
expires: "Jan 31 2020" expires: "Jan 31 2020"
# Connect to default database, create rails user, set its password (MD5-hashed), and grant privilege to create other # Connect to default database, create rails user, set its password (MD5-hashed),
# databases and demote rails from super user status if user exists # and grant privilege to create other databases and demote rails from super user status if user exists
- postgresql_user: - name: Create rails user, set MD5-hashed password, grant privs
postgresql_user:
name: rails name: rails
password: md59543f1d82624df2b31672ec0f7050460 password: md59543f1d82624df2b31672ec0f7050460
role_attr_flags: CREATEDB,NOSUPERUSER role_attr_flags: CREATEDB,NOSUPERUSER
# Connect to acme database and remove test user privileges from there - name: Connect to acme database and remove test user privileges from there
- postgresql_user: postgresql_user:
db: acme db: acme
name: test name: test
priv: "ALL/products:ALL" priv: "ALL/products:ALL"
state: absent state: absent
fail_on_user: no fail_on_user: no
# Connect to test database, remove test user from cluster - name: Connect to test database, remove test user from cluster
- postgresql_user: postgresql_user:
db: test db: test
name: test name: test
priv: ALL priv: ALL
state: absent state: absent
# Connect to acme database and set user's password with no expire date - name: Connect to acme database and set user's password with no expire date
- postgresql_user: postgresql_user:
db: acme db: acme
name: django name: django
password: mysupersecretword password: mysupersecretword
@ -212,13 +239,22 @@ EXAMPLES = '''
# Example privileges string format # Example privileges string format
# INSERT,UPDATE/table:SELECT/anothertable:ALL # INSERT,UPDATE/table:SELECT/anothertable:ALL
# Connect to test database and remove an existing user's password - name: Connect to test database and remove an existing user's password
- postgresql_user: postgresql_user:
db: test db: test
user: test user: test
password: "" password: ""
''' '''
RETURN = r'''
queries:
description: List of executed queries.
returned: always
type: list
sample: ['CREATE USER "alice"', 'GRANT CONNECT ON DATABASE "acme" TO "alice"']
version_added: '2.8'
'''
import itertools import itertools
import re import re
import traceback import traceback
@ -228,15 +264,14 @@ PSYCOPG2_IMP_ERR = None
try: try:
import psycopg2 import psycopg2
import psycopg2.extras import psycopg2.extras
HAS_PSYCOPG2 = True
except ImportError: except ImportError:
PSYCOPG2_IMP_ERR = traceback.format_exc() PSYCOPG2_IMP_ERR = traceback.format_exc()
postgresqldb_found = False HAS_PSYCOPG2 = False
else:
postgresqldb_found = True
import ansible.module_utils.postgres as pgutils
from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.database import pg_quote_identifier, SQLParseError from ansible.module_utils.database import pg_quote_identifier, SQLParseError
from ansible.module_utils.postgres import postgres_common_argument_spec
from ansible.module_utils._text import to_bytes, to_native from ansible.module_utils._text import to_bytes, to_native
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
@ -254,6 +289,8 @@ PRIV_TO_AUTHID_COLUMN = dict(SUPERUSER='rolsuper', CREATEROLE='rolcreaterole',
CREATEDB='rolcreatedb', INHERIT='rolinherit', LOGIN='rolcanlogin', CREATEDB='rolcreatedb', INHERIT='rolinherit', LOGIN='rolcanlogin',
REPLICATION='rolreplication', BYPASSRLS='rolbypassrls') REPLICATION='rolreplication', BYPASSRLS='rolbypassrls')
executed_queries = []
class InvalidFlagsError(Exception): class InvalidFlagsError(Exception):
pass pass
@ -292,6 +329,7 @@ def user_add(cursor, user, password, role_attr_flags, encrypted, expires, conn_l
query.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit}) query.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit})
query.append(role_attr_flags) query.append(role_attr_flags)
query = ' '.join(query) query = ' '.join(query)
executed_queries.append(query)
cursor.execute(query, query_password_data) cursor.execute(query, query_password_data)
return True return True
@ -484,7 +522,9 @@ def user_delete(cursor, user):
"""Try to remove a user. Returns True if successful otherwise False""" """Try to remove a user. Returns True if successful otherwise False"""
cursor.execute("SAVEPOINT ansible_pgsql_user_delete") cursor.execute("SAVEPOINT ansible_pgsql_user_delete")
try: try:
cursor.execute("DROP USER %s" % pg_quote_identifier(user, 'role')) query = "DROP USER %s" % pg_quote_identifier(user, 'role')
executed_queries.append(query)
cursor.execute(query)
except Exception: except Exception:
cursor.execute("ROLLBACK TO SAVEPOINT ansible_pgsql_user_delete") cursor.execute("ROLLBACK TO SAVEPOINT ansible_pgsql_user_delete")
cursor.execute("RELEASE SAVEPOINT ansible_pgsql_user_delete") cursor.execute("RELEASE SAVEPOINT ansible_pgsql_user_delete")
@ -516,9 +556,9 @@ def get_table_privileges(cursor, user, table):
schema, table = table.split('.', 1) schema, table = table.split('.', 1)
else: else:
schema = 'public' schema = 'public'
query = '''SELECT privilege_type FROM information_schema.role_table_grants query = ("SELECT privilege_type FROM information_schema.role_table_grants "
WHERE grantee=%s AND table_name=%s AND table_schema=%s''' "WHERE grantee='%s' AND table_name='%s' AND table_schema='%s'" % (user, table, schema))
cursor.execute(query, (user, table, schema)) cursor.execute(query)
return frozenset([x[0] for x in cursor.fetchall()]) return frozenset([x[0] for x in cursor.fetchall()])
@ -527,6 +567,7 @@ def grant_table_privileges(cursor, user, table, privs):
privs = ', '.join(privs) privs = ', '.join(privs)
query = 'GRANT %s ON TABLE %s TO %s' % ( query = 'GRANT %s ON TABLE %s TO %s' % (
privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role')) privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role'))
executed_queries.append(query)
cursor.execute(query) cursor.execute(query)
@ -535,6 +576,7 @@ def revoke_table_privileges(cursor, user, table, privs):
privs = ', '.join(privs) privs = ', '.join(privs)
query = 'REVOKE %s ON TABLE %s FROM %s' % ( query = 'REVOKE %s ON TABLE %s FROM %s' % (
privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role')) privs, pg_quote_identifier(table, 'table'), pg_quote_identifier(user, 'role'))
executed_queries.append(query)
cursor.execute(query) cursor.execute(query)
@ -585,6 +627,8 @@ def grant_database_privileges(cursor, user, db, privs):
query = 'GRANT %s ON DATABASE %s TO %s' % ( query = 'GRANT %s ON DATABASE %s TO %s' % (
privs, pg_quote_identifier(db, 'database'), privs, pg_quote_identifier(db, 'database'),
pg_quote_identifier(user, 'role')) pg_quote_identifier(user, 'role'))
executed_queries.append(query)
cursor.execute(query) cursor.execute(query)
@ -598,6 +642,8 @@ def revoke_database_privileges(cursor, user, db, privs):
query = 'REVOKE %s ON DATABASE %s FROM %s' % ( query = 'REVOKE %s ON DATABASE %s FROM %s' % (
privs, pg_quote_identifier(db, 'database'), privs, pg_quote_identifier(db, 'database'),
pg_quote_identifier(user, 'role')) pg_quote_identifier(user, 'role'))
executed_queries.append(query)
cursor.execute(query) cursor.execute(query)
@ -746,24 +792,21 @@ def get_valid_flags_by_version(cursor):
def main(): def main():
argument_spec = pgutils.postgres_common_argument_spec() argument_spec = postgres_common_argument_spec()
argument_spec.update(dict( argument_spec.update(
user=dict(required=True, aliases=['name']), user=dict(type='str', required=True, aliases=['name']),
password=dict(default=None, no_log=True), password=dict(type='str', default=None, no_log=True),
state=dict(default="present", choices=["absent", "present"]), state=dict(type='str', default='present', choices=['absent', 'present']),
priv=dict(default=None), priv=dict(type='str', default=None),
db=dict(default=''), db=dict(type='str', default='', aliases=['login_db']),
fail_on_user=dict(type='bool', default='yes'), fail_on_user=dict(type='bool', default='yes', aliases=['fail_on_role']),
role_attr_flags=dict(default=''), role_attr_flags=dict(type='str', default=''),
encrypted=dict(type='bool', default='yes'), encrypted=dict(type='bool', default='yes'),
no_password_changes=dict(type='bool', default='no'), no_password_changes=dict(type='bool', default='no'),
expires=dict(default=None), expires=dict(type='str', default=None),
ssl_mode=dict(default='prefer', choices=[
'disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']),
ca_cert=dict(default=None, aliases=['ssl_rootcert']),
conn_limit=dict(type='int', default=None), conn_limit=dict(type='int', default=None),
session_role=dict(), session_role=dict(type='str'),
)) )
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True supports_check_mode=True
@ -786,8 +829,9 @@ def main():
expires = module.params["expires"] expires = module.params["expires"]
sslrootcert = module.params["ca_cert"] sslrootcert = module.params["ca_cert"]
conn_limit = module.params["conn_limit"] conn_limit = module.params["conn_limit"]
role_attr_flags = module.params["role_attr_flags"]
if not postgresqldb_found: if not HAS_PSYCOPG2:
module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR) module.fail_json(msg=missing_required_lib('psycopg2'), exception=PSYCOPG2_IMP_ERR)
# To use defaults values, keyword arguments must be absent, so # To use defaults values, keyword arguments must be absent, so
@ -823,10 +867,10 @@ def main():
if 'sslrootcert' in e.args[0]: if 'sslrootcert' in e.args[0]:
module.fail_json( module.fail_json(
msg='Postgresql server must be at least version 8.4 to support sslrootcert') msg='Postgresql server must be at least version 8.4 to support sslrootcert')
module.fail_json(msg="unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) module.fail_json(msg="Unable to connect to database: %s" % to_native(e), exception=traceback.format_exc())
except Exception as e: except Exception as e:
module.fail_json(msg="unable to connect to database: %s" % to_native(e), exception=traceback.format_exc()) module.fail_json(msg="Unable to connect to database: %s" % to_native(e), exception=traceback.format_exc())
if session_role: if session_role:
try: try:
@ -835,7 +879,7 @@ def main():
module.fail_json(msg="Could not switch role: %s" % to_native(e), exception=traceback.format_exc()) module.fail_json(msg="Could not switch role: %s" % to_native(e), exception=traceback.format_exc())
try: try:
role_attr_flags = parse_role_attrs(cursor, module.params["role_attr_flags"]) role_attr_flags = parse_role_attrs(cursor, role_attr_flags)
except InvalidFlagsError as e: except InvalidFlagsError as e:
module.fail_json(msg=to_native(e), exception=traceback.format_exc()) module.fail_json(msg=to_native(e), exception=traceback.format_exc())
@ -877,7 +921,7 @@ def main():
module.fail_json(msg=to_native(e), exception=traceback.format_exc()) module.fail_json(msg=to_native(e), exception=traceback.format_exc())
changed = changed or user_removed changed = changed or user_removed
if fail_on_user and not user_removed: if fail_on_user and not user_removed:
msg = "unable to remove user" msg = "Unable to remove user"
module.fail_json(msg=msg) module.fail_json(msg=msg)
kw['user_removed'] = user_removed kw['user_removed'] = user_removed
@ -888,6 +932,7 @@ def main():
db_connection.commit() db_connection.commit()
kw['changed'] = changed kw['changed'] = changed
kw['queries'] = executed_queries
module.exit_json(**kw) module.exit_json(**kw)

@ -15,7 +15,7 @@
postgresql_user: postgresql_user:
<<: *parameters <<: *parameters
state: "present" state: "present"
role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,login{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}" role_attr_flags: "SUPERUSER,CREATEROLE,CREATEDB,INHERIT,LOGIN{{ bypassrls_supported | ternary(',BYPASSRLS', '') }}"
no_password_changes: '{{ no_password_changes }}' # no_password_changes is ignored when user doesn't already exist no_password_changes: '{{ no_password_changes }}' # no_password_changes is ignored when user doesn't already exist
- name: Check that the user has the requested role attributes - name: Check that the user has the requested role attributes

@ -334,13 +334,6 @@ lib/ansible/modules/database/mongodb/mongodb_user.py E322
lib/ansible/modules/database/mysql/mysql_db.py E210 lib/ansible/modules/database/mysql/mysql_db.py E210
lib/ansible/modules/database/mysql/mysql_user.py E322 lib/ansible/modules/database/mysql/mysql_user.py E322
lib/ansible/modules/database/postgresql/postgresql_db.py E210 lib/ansible/modules/database/postgresql/postgresql_db.py E210
lib/ansible/modules/database/postgresql/postgresql_ext.py E322
lib/ansible/modules/database/postgresql/postgresql_ext.py E324
lib/ansible/modules/database/postgresql/postgresql_lang.py E324
lib/ansible/modules/database/postgresql/postgresql_schema.py E322
lib/ansible/modules/database/postgresql/postgresql_schema.py E324
lib/ansible/modules/database/postgresql/postgresql_user.py E322
lib/ansible/modules/database/postgresql/postgresql_user.py E324
lib/ansible/modules/database/postgresql/postgresql_user.py E326 lib/ansible/modules/database/postgresql/postgresql_user.py E326
lib/ansible/modules/database/proxysql/proxysql_backend_servers.py E322 lib/ansible/modules/database/proxysql/proxysql_backend_servers.py E322
lib/ansible/modules/database/proxysql/proxysql_global_variables.py E322 lib/ansible/modules/database/proxysql/proxysql_global_variables.py E322

Loading…
Cancel
Save