From 0079b8eaa205dc72df84efbc069670aaaeeb5143 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Thu, 12 Dec 2019 16:10:52 +0300 Subject: [PATCH] mysql_info: add return_empty_dbs parameter (#65755) * Bugfix of 65727: mysql_info doesn't list empty DBs * add changelog * mysql_info: add return_empty_dbs parameter * fix --- ...65755-mysql_info_doesnt_list_empty_dbs.yml | 2 + .../modules/database/mysql/mysql_info.py | 37 +++++++++++--- .../targets/mysql_info/tasks/main.yml | 50 +++++++++++++++++++ 3 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/65755-mysql_info_doesnt_list_empty_dbs.yml diff --git a/changelogs/fragments/65755-mysql_info_doesnt_list_empty_dbs.yml b/changelogs/fragments/65755-mysql_info_doesnt_list_empty_dbs.yml new file mode 100644 index 00000000000..2f1b9b67bab --- /dev/null +++ b/changelogs/fragments/65755-mysql_info_doesnt_list_empty_dbs.yml @@ -0,0 +1,2 @@ +minor_changes: +- mysql_info - add ``return_empty_dbs`` parameter to list empty databases (https://github.com/ansible/ansible/issues/65727). diff --git a/lib/ansible/modules/database/mysql/mysql_info.py b/lib/ansible/modules/database/mysql/mysql_info.py index eb57a82f945..4d3b99e1092 100644 --- a/lib/ansible/modules/database/mysql/mysql_info.py +++ b/lib/ansible/modules/database/mysql/mysql_info.py @@ -45,6 +45,12 @@ options: type: list elements: str version_added: '2.10' + return_empty_dbs: + description: + - Includes names of empty databases to returned dictionary. + type: bool + default: no + version_added: '2.10' notes: - Calculating the size of a database might be slow, depending on the number and size of tables in it. @@ -106,13 +112,14 @@ EXAMPLES = r''' - databases - version -- name: Collect info about databases excluding their sizes +- name: Collect info about databases including empty and excluding their sizes become: yes mysql_info: config_file: /home/alice/.my.cnf filter: - databases exclude_fields: db_size + return_empty_dbs: yes ''' RETURN = r''' @@ -244,14 +251,14 @@ class MySQL_Info(object): 'slave_status': {}, } - def get_info(self, filter_, exclude_fields): + def get_info(self, filter_, exclude_fields, return_empty_dbs): """Get MySQL instance information based on filter_. Arguments: filter_ (list): List of collected subsets (e.g., databases, users, etc.), when it is empty, return all available information. """ - self.__collect(exclude_fields) + self.__collect(exclude_fields, return_empty_dbs) inc_list = [] exc_list = [] @@ -285,9 +292,9 @@ class MySQL_Info(object): else: return self.info - def __collect(self, exclude_fields): + def __collect(self, exclude_fields, return_empty_dbs): """Collect all possible subsets.""" - self.__get_databases(exclude_fields) + self.__get_databases(exclude_fields, return_empty_dbs) self.__get_global_variables() self.__get_global_status() self.__get_engines() @@ -408,7 +415,7 @@ class MySQL_Info(object): if vname not in ('Host', 'User'): self.info['users'][host][user][vname] = self.__convert(val) - def __get_databases(self, exclude_fields): + def __get_databases(self, exclude_fields, return_empty_dbs): """Get info about databases.""" if not exclude_fields: query = ('SELECT table_schema AS "name", ' @@ -428,6 +435,20 @@ class MySQL_Info(object): if not exclude_fields or 'db_size' not in exclude_fields: self.info['databases'][db['name']]['size'] = int(db['size']) + # If empty dbs are not needed in the returned dict, exit from the method + if not return_empty_dbs: + return None + + # Add info about empty databases (issue #65727): + res = self.__exec_sql('SHOW DATABASES') + if res: + for db in res: + if db['Database'] not in self.info['databases']: + self.info['databases'][db['Database']] = {} + + if not exclude_fields or 'db_size' not in exclude_fields: + self.info['databases'][db['Database']]['size'] = 0 + def __exec_sql(self, query, ddl=False): """Execute SQL. @@ -460,6 +481,7 @@ def main(): login_db=dict(type='str'), filter=dict(type='list'), exclude_fields=dict(type='list'), + return_empty_dbs=dict(type='bool', default=False), ) # The module doesn't support check_mode @@ -479,6 +501,7 @@ def main(): config_file = module.params['config_file'] filter_ = module.params['filter'] exclude_fields = module.params['exclude_fields'] + return_empty_dbs = module.params['return_empty_dbs'] if filter_: filter_ = [f.strip() for f in filter_] @@ -502,7 +525,7 @@ def main(): mysql = MySQL_Info(module, cursor) - module.exit_json(changed=False, **mysql.get_info(filter_, exclude_fields)) + module.exit_json(changed=False, **mysql.get_info(filter_, exclude_fields, return_empty_dbs)) if __name__ == '__main__': diff --git a/test/integration/targets/mysql_info/tasks/main.yml b/test/integration/targets/mysql_info/tasks/main.yml index 7ca76c3ecda..f58d3878e89 100644 --- a/test/integration/targets/mysql_info/tasks/main.yml +++ b/test/integration/targets/mysql_info/tasks/main.yml @@ -138,3 +138,53 @@ - result.changed == false - result.databases != {} - result.databases.mysql == {} + +######################################################## +# Issue #65727, empty databases must be in returned dict +# +- name: Create empty database acme + mysql_db: + login_user: '{{ user_name }}' + login_password: '{{ user_pass }}' + name: acme + +- name: Collect info about databases + mysql_info: + login_user: '{{ user_name }}' + login_password: '{{ user_pass }}' + filter: + - databases + return_empty_dbs: yes + register: result + +# Check acme is in returned dict +- assert: + that: + - result.changed == false + - result.databases.acme.size == 0 + - result.databases.mysql != {} + +- name: Collect info about databases excluding their sizes + mysql_info: + login_user: '{{ user_name }}' + login_password: '{{ user_pass }}' + filter: + - databases + exclude_fields: + - db_size + return_empty_dbs: yes + register: result + +# Check acme is in returned dict +- assert: + that: + - result.changed == false + - result.databases.acme == {} + - result.databases.mysql == {} + +- name: Remove acme database + mysql_db: + login_user: '{{ user_name }}' + login_password: '{{ user_pass }}' + name: acme + state: absent