diff --git a/lib/ansible/modules/database/postgresql/postgresql_user.py b/lib/ansible/modules/database/postgresql/postgresql_user.py index 5993f9f5ba..da088b1556 100644 --- a/lib/ansible/modules/database/postgresql/postgresql_user.py +++ b/lib/ansible/modules/database/postgresql/postgresql_user.py @@ -138,6 +138,12 @@ options: required: false default: null version_added: '2.3' + conn_limit: + description: + - Specifies the user connection limit. + required: false + default: null + version_added: '2.4' notes: - The default authentication assumes that you are either logging in as or sudo'ing to the postgres account on the host. @@ -254,7 +260,7 @@ def user_exists(cursor, user): return cursor.rowcount > 0 -def user_add(cursor, user, password, role_attr_flags, encrypted, expires): +def user_add(cursor, user, password, role_attr_flags, encrypted, expires, conn_limit): """Create a new database user (role).""" # Note: role_attr_flags escaped by parse_role_attrs and encrypted is a # literal @@ -266,6 +272,8 @@ def user_add(cursor, user, password, role_attr_flags, encrypted, expires): query.append("PASSWORD %(password)s") if expires is not None: query.append("VALID UNTIL %(expires)s") + if conn_limit is not None: + query.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit}) query.append(role_attr_flags) query = ' '.join(query) cursor.execute(query, query_password_data) @@ -303,7 +311,7 @@ def user_should_we_change_password(current_role_attrs, user, password, encrypted return pwchanging -def user_alter(db_connection, module, user, password, role_attr_flags, encrypted, expires, no_password_changes): +def user_alter(db_connection, module, user, password, role_attr_flags, encrypted, expires, no_password_changes, conn_limit): """Change user password and/or attributes. Return True if changed, False otherwise.""" changed = False @@ -319,7 +327,7 @@ def user_alter(db_connection, module, user, password, role_attr_flags, encrypted return False # Handle passwords. - if not no_password_changes and (password is not None or role_attr_flags != '' or expires is not None): + if not no_password_changes and (password is not None or role_attr_flags != '' or expires is not None or conn_limit is not None): # Select password and all flag-like columns in order to verify changes. try: select = "SELECT * FROM pg_authid where rolname=%(user)s" @@ -352,7 +360,9 @@ def user_alter(db_connection, module, user, password, role_attr_flags, encrypted else: expires_changing = False - if not pwchanging and not role_attr_flags_changing and not expires_changing: + conn_limit_changing = (conn_limit is not None and conn_limit != current_role_attrs['rolconnlimit']) + + if not pwchanging and not role_attr_flags_changing and not expires_changing and not conn_limit_changing: return False alter = ['ALTER USER %(user)s' % {"user": pg_quote_identifier(user, 'role')}] @@ -364,6 +374,8 @@ def user_alter(db_connection, module, user, password, role_attr_flags, encrypted alter.append('WITH %s' % role_attr_flags) if expires is not None: alter.append("VALID UNTIL %(expires)s") + if conn_limit is not None: + alter.append("CONNECTION LIMIT %(conn_limit)s" % {"conn_limit": conn_limit}) query_password_data = dict(password=password, expires=expires) try: @@ -730,7 +742,8 @@ def main(): expires=dict(default=None), ssl_mode=dict(default='prefer', choices=[ 'disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full']), - ssl_rootcert=dict(default=None) + ssl_rootcert=dict(default=None), + conn_limit=dict(default=None) ), supports_check_mode=True ) @@ -750,6 +763,7 @@ def main(): encrypted = "UNENCRYPTED" expires = module.params["expires"] sslrootcert = module.params["ssl_rootcert"] + conn_limit = module.params["conn_limit"] if not postgresqldb_found: module.fail_json(msg="the python psycopg2 module is required") @@ -805,13 +819,13 @@ def main(): if user_exists(cursor, user): try: changed = user_alter(db_connection, module, user, password, - role_attr_flags, encrypted, expires, no_password_changes) + 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) + role_attr_flags, encrypted, expires, conn_limit) except SQLParseError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc()) try: