diff --git a/plugins/module_utils/mysql.py b/plugins/module_utils/mysql.py index 5af9c20..484f170 100644 --- a/plugins/module_utils/mysql.py +++ b/plugins/module_utils/mysql.py @@ -43,7 +43,7 @@ def parse_from_mysql_config_file(cnf): def mysql_connect(module, login_user=None, login_password=None, config_file='', ssl_cert=None, ssl_key=None, ssl_ca=None, db=None, cursor_class=None, connect_timeout=30, - autocommit=False, config_overrides_defaults=False, check_hostname=None): + autocommit=False, config_overrides_defaults=False, check_hostname=None, protocol=None): config = {} if config_file and os.path.exists(config_file): @@ -88,6 +88,8 @@ def mysql_connect(module, login_user=None, login_password=None, config_file='', config['ssl']['ca'] = ssl_ca if db is not None: config['db'] = db + if protocol is not None and protocol.upper() in ('TCP', 'SOCKET', 'PIPE', 'MEMORY'): + config['protocol'] = protocol.upper() if connect_timeout is not None: config['connect_timeout'] = connect_timeout if check_hostname is not None: @@ -132,6 +134,7 @@ def mysql_common_argument_spec(): client_key=dict(type='path', aliases=['ssl_key']), ca_cert=dict(type='path', aliases=['ssl_ca']), check_hostname=dict(type='bool', default=None), + protocol=dict(type='str', default=None), ) diff --git a/plugins/modules/mysql_db.py b/plugins/modules/mysql_db.py index c2a6fd8..285aa9e 100644 --- a/plugins/modules/mysql_db.py +++ b/plugins/modules/mysql_db.py @@ -150,6 +150,17 @@ options: type: bool default: no version_added: '0.1.0' + protocol: + description: + - Provide protocol arguments on how to connect to MySQL database instance. + Used when I(state=dump), I(state=import), I(state=present) and I(state=absent) ignored otherwise. + Use case, when needing intermediary MySQL database instance and relying on MySQL Official container image + and need "--protocol=TCP". When using MySQL Official container image, you may run your container with + docker "--net=host" flag in that case you shouldn't need to specify "login_host". Otherwise you will have + to connect to the LAN/WAN IP address or hostname and it that case you need to with the binding as you need to + specified the "login_host" in complement to "protocol". + type: str + version_added: '2.3.3' seealso: - module: community.mysql.mysql_info @@ -207,6 +218,14 @@ EXAMPLES = r''' state: import target: /tmp/dump.sql.bz2 +- name: Restore database in MySQL Official container image instance + community.mysql.mysql_db: + name: my_db + state: import + target: /tmp/dump.sql.bz2 + protocol: tcp + login_host: + - name: Restore database ignoring errors community.mysql.mysql_db: name: my_db @@ -349,7 +368,7 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port, single_transaction=None, quick=None, ignore_tables=None, hex_blob=None, encoding=None, force=False, master_data=0, skip_lock_tables=False, dump_extra_args=None, unsafe_password=False, restrict_config_file=False, - check_implicit_admin=False): + check_implicit_admin=False, protocol=None): cmd = module.get_bin_path('mysqldump', True) # If defined, mysqldump demands --defaults-extra-file be the first option if config_file: @@ -382,6 +401,8 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port, cmd += " --socket=%s" % shlex_quote(socket) else: cmd += " --host=%s --port=%i" % (shlex_quote(host), port) + if protocol is not None: + cmd += " --host=%s" % protocol if all_databases: cmd += " --all-databases" @@ -429,7 +450,7 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port, def db_import(module, host, user, password, db_name, target, all_databases, port, config_file, socket=None, ssl_cert=None, ssl_key=None, ssl_ca=None, encoding=None, force=False, use_shell=False, unsafe_password=False, restrict_config_file=False, - check_implicit_admin=False): + check_implicit_admin=False, protocol=None): if not os.path.exists(target): return module.fail_json(msg="target %s does not exist on the host" % target) @@ -471,6 +492,8 @@ def db_import(module, host, user, password, db_name, target, all_databases, port if not all_databases: cmd.append("--one-database") cmd.append(shlex_quote(''.join(db_name))) + if protocol is not None: + cmd.append("--protocol=%s" % protocol) comp_prog_path = None if os.path.splitext(target)[-1] == '.gz': @@ -562,6 +585,7 @@ def main(): restrict_config_file=dict(type='bool', default=False), check_implicit_admin=dict(type='bool', default=False), config_overrides_defaults=dict(type='bool', default=False), + protocol=dict(type='str', default=None, choices=['tcp', 'socket', 'pipe', 'memory']), ) module = AnsibleModule( @@ -610,6 +634,7 @@ def main(): restrict_config_file = module.params["restrict_config_file"] check_implicit_admin = module.params['check_implicit_admin'] config_overrides_defaults = module.params['config_overrides_defaults'] + protocol = module.params['protocol'] if len(db) > 1 and state == 'import': module.fail_json(msg="Multiple databases are not supported with state=import") @@ -628,17 +653,21 @@ def main(): cursor = None if check_implicit_admin: try: - cursor, db_conn = mysql_connect(module, 'root', '', config_file, ssl_cert, ssl_key, ssl_ca, - connect_timeout=connect_timeout, check_hostname=check_hostname, - config_overrides_defaults=config_overrides_defaults) + cursor, db_conn = mysql_connect( + module, 'root', '', config_file, ssl_cert, ssl_key, ssl_ca, protocol, + connect_timeout=connect_timeout, check_hostname=check_hostname, + config_overrides_defaults=config_overrides_defaults + ) except Exception as e: check_implicit_admin = False pass if not cursor: - cursor, db_conn = mysql_connect(module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, - connect_timeout=connect_timeout, config_overrides_defaults=config_overrides_defaults, - check_hostname=check_hostname) + cursor, db_conn = mysql_connect( + module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, protocol, + connect_timeout=connect_timeout, config_overrides_defaults=config_overrides_defaults, + check_hostname=check_hostname + ) except Exception as e: if os.path.exists(config_file): module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. " @@ -690,7 +719,7 @@ def main(): ssl_ca, single_transaction, quick, ignore_tables, hex_blob, encoding, force, master_data, skip_lock_tables, dump_extra_args, unsafe_login_password, restrict_config_file, - check_implicit_admin) + check_implicit_admin, protocol) if rc != 0: module.fail_json(msg="%s" % stderr) module.exit_json(changed=True, db=db_name, db_list=db, msg=stdout, @@ -710,7 +739,7 @@ def main(): login_port, config_file, socket, ssl_cert, ssl_key, ssl_ca, encoding, force, use_shell, unsafe_login_password, - restrict_config_file, check_implicit_admin) + restrict_config_file, check_implicit_admin, protocol) if rc != 0: module.fail_json(msg="%s" % stderr) module.exit_json(changed=True, db=db_name, db_list=db, msg=stdout, diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 6f57403..656adf1 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -526,6 +526,7 @@ def main(): filter=dict(type='list'), exclude_fields=dict(type='list'), return_empty_dbs=dict(type='bool', default=False), + protocol=dict(type='str', default=None, choices=['tcp', 'socket', 'pipe', 'memory']), ) module = AnsibleModule( @@ -545,6 +546,7 @@ def main(): filter_ = module.params['filter'] exclude_fields = module.params['exclude_fields'] return_empty_dbs = module.params['return_empty_dbs'] + protocol = module.params['protocol'] if filter_: filter_ = [f.strip() for f in filter_] @@ -556,10 +558,11 @@ def main(): module.fail_json(msg=mysql_driver_fail_msg) try: - cursor, db_conn = mysql_connect(module, login_user, login_password, - config_file, ssl_cert, ssl_key, ssl_ca, db, - check_hostname=check_hostname, - connect_timeout=connect_timeout, cursor_class='DictCursor') + cursor, db_conn = mysql_connect( + module, login_user, login_password, config_file, + ssl_cert, ssl_key, ssl_ca, db, protocol, + check_hostname=check_hostname, + connect_timeout=connect_timeout, cursor_class='DictCursor') except Exception as e: module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. " "Exception message: %s" % (config_file, to_native(e))) diff --git a/plugins/modules/mysql_query.py b/plugins/modules/mysql_query.py index fc789c5..ffe80ed 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -129,6 +129,7 @@ def main(): positional_args=dict(type='list'), named_args=dict(type='dict'), single_transaction=dict(type='bool', default=False), + protocol=dict(type='str', default=None, choices=['tcp', 'socket', 'pipe', 'memory']), ) module = AnsibleModule( @@ -148,6 +149,7 @@ def main(): check_hostname = module.params['check_hostname'] config_file = module.params['config_file'] query = module.params["query"] + protocol = module.params["protocol"] if not isinstance(query, (str, list)): module.fail_json(msg="the query option value must be a string or list, passed %s" % type(query)) @@ -176,11 +178,13 @@ def main(): # Connect to DB: try: - cursor, db_connection = mysql_connect(module, login_user, login_password, - config_file, ssl_cert, ssl_key, ssl_ca, db, - check_hostname=check_hostname, - connect_timeout=connect_timeout, - cursor_class='DictCursor', autocommit=autocommit) + cursor, db_connection = mysql_connect( + module, login_user, login_password, + config_file, ssl_cert, ssl_key, ssl_ca, db, protocol, + check_hostname=check_hostname, + connect_timeout=connect_timeout, + cursor_class='DictCursor', autocommit=autocommit + ) except Exception as e: module.fail_json(msg="unable to connect to database, check login_user and " "login_password are correct or %s has the credentials. " diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index e1d0a92..39649b8 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -355,6 +355,7 @@ def main(): plugin_auth_string=dict(default=None, type='str'), resource_limits=dict(type='dict'), force_context=dict(type='bool', default=False), + protocol=dict(type='str', default=None, choices=['tcp', 'socket', 'pipe', 'memory']), ) module = AnsibleModule( argument_spec=argument_spec, @@ -382,6 +383,7 @@ def main(): db = '' if module.params["force_context"]: db = 'mysql' + protocol = module.params["protocol"] sql_log_bin = module.params["sql_log_bin"] plugin = module.params["plugin"] plugin_hash_string = module.params["plugin_hash_string"] @@ -400,14 +402,18 @@ def main(): try: if check_implicit_admin: try: - cursor, db_conn = mysql_connect(module, "root", "", config_file, ssl_cert, ssl_key, ssl_ca, db, - connect_timeout=connect_timeout, check_hostname=check_hostname) + cursor, db_conn = mysql_connect( + module, "root", "", config_file, ssl_cert, ssl_key, ssl_ca, db, protocol, + connect_timeout=connect_timeout, check_hostname=check_hostname + ) except Exception: pass if not cursor: - cursor, db_conn = mysql_connect(module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, db, - connect_timeout=connect_timeout, check_hostname=check_hostname) + cursor, db_conn = mysql_connect( + module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, db, protocol, + connect_timeout=connect_timeout, check_hostname=check_hostname + ) except Exception as e: module.fail_json(msg="unable to connect to database, check login_user and login_password are correct or %s has the credentials. " "Exception message: %s" % (config_file, to_native(e))) diff --git a/plugins/modules/mysql_variables.py b/plugins/modules/mysql_variables.py index 06beee3..e4fe592 100644 --- a/plugins/modules/mysql_variables.py +++ b/plugins/modules/mysql_variables.py @@ -175,6 +175,7 @@ def main(): variable=dict(type='str'), value=dict(type='str'), mode=dict(type='str', choices=['global', 'persist', 'persist_only'], default='global'), + protocol=dict(type='str', default=None, choices=['tcp', 'socket', 'pipe', 'memory']), ) module = AnsibleModule( @@ -193,6 +194,7 @@ def main(): mysqlvar = module.params["variable"] value = module.params["value"] mode = module.params["mode"] + protocol = module.params["protocol"] if mysqlvar is None: module.fail_json(msg="Cannot run without variable to operate with") @@ -204,8 +206,10 @@ def main(): warnings.filterwarnings('error', category=mysql_driver.Warning) try: - cursor, db_conn = mysql_connect(module, user, password, config_file, ssl_cert, ssl_key, ssl_ca, db, - connect_timeout=connect_timeout, check_hostname=check_hostname) + cursor, db_conn = mysql_connect( + module, user, password, config_file, ssl_cert, ssl_key, ssl_ca, db, protocol, + connect_timeout=connect_timeout, check_hostname=check_hostname + ) except Exception as e: if os.path.exists(config_file): module.fail_json(msg=("unable to connect to database, check login_user and "