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
This commit is contained in:
Andrew Klychkov 2019-12-12 16:10:52 +03:00 committed by Felix Fontein
parent 80333f9c4b
commit 0079b8eaa2
3 changed files with 82 additions and 7 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- mysql_info - add ``return_empty_dbs`` parameter to list empty databases (https://github.com/ansible/ansible/issues/65727).

View file

@ -45,6 +45,12 @@ options:
type: list type: list
elements: str elements: str
version_added: '2.10' 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: notes:
- Calculating the size of a database might be slow, depending on the number and size of tables in it. - 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 - databases
- version - version
- name: Collect info about databases excluding their sizes - name: Collect info about databases including empty and excluding their sizes
become: yes become: yes
mysql_info: mysql_info:
config_file: /home/alice/.my.cnf config_file: /home/alice/.my.cnf
filter: filter:
- databases - databases
exclude_fields: db_size exclude_fields: db_size
return_empty_dbs: yes
''' '''
RETURN = r''' RETURN = r'''
@ -244,14 +251,14 @@ class MySQL_Info(object):
'slave_status': {}, '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_. """Get MySQL instance information based on filter_.
Arguments: Arguments:
filter_ (list): List of collected subsets (e.g., databases, users, etc.), filter_ (list): List of collected subsets (e.g., databases, users, etc.),
when it is empty, return all available information. when it is empty, return all available information.
""" """
self.__collect(exclude_fields) self.__collect(exclude_fields, return_empty_dbs)
inc_list = [] inc_list = []
exc_list = [] exc_list = []
@ -285,9 +292,9 @@ class MySQL_Info(object):
else: else:
return self.info return self.info
def __collect(self, exclude_fields): def __collect(self, exclude_fields, return_empty_dbs):
"""Collect all possible subsets.""" """Collect all possible subsets."""
self.__get_databases(exclude_fields) self.__get_databases(exclude_fields, return_empty_dbs)
self.__get_global_variables() self.__get_global_variables()
self.__get_global_status() self.__get_global_status()
self.__get_engines() self.__get_engines()
@ -408,7 +415,7 @@ class MySQL_Info(object):
if vname not in ('Host', 'User'): if vname not in ('Host', 'User'):
self.info['users'][host][user][vname] = self.__convert(val) 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.""" """Get info about databases."""
if not exclude_fields: if not exclude_fields:
query = ('SELECT table_schema AS "name", ' 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: if not exclude_fields or 'db_size' not in exclude_fields:
self.info['databases'][db['name']]['size'] = int(db['size']) 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): def __exec_sql(self, query, ddl=False):
"""Execute SQL. """Execute SQL.
@ -460,6 +481,7 @@ def main():
login_db=dict(type='str'), login_db=dict(type='str'),
filter=dict(type='list'), filter=dict(type='list'),
exclude_fields=dict(type='list'), exclude_fields=dict(type='list'),
return_empty_dbs=dict(type='bool', default=False),
) )
# The module doesn't support check_mode # The module doesn't support check_mode
@ -479,6 +501,7 @@ def main():
config_file = module.params['config_file'] config_file = module.params['config_file']
filter_ = module.params['filter'] filter_ = module.params['filter']
exclude_fields = module.params['exclude_fields'] exclude_fields = module.params['exclude_fields']
return_empty_dbs = module.params['return_empty_dbs']
if filter_: if filter_:
filter_ = [f.strip() for f in filter_] filter_ = [f.strip() for f in filter_]
@ -502,7 +525,7 @@ def main():
mysql = MySQL_Info(module, cursor) 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__': if __name__ == '__main__':

View file

@ -138,3 +138,53 @@
- result.changed == false - result.changed == false
- result.databases != {} - result.databases != {}
- result.databases.mysql == {} - 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