From 0b9523c6eb08044a7a7407e0cee21bd149be9d67 Mon Sep 17 00:00:00 2001 From: Jorge-Rodriguez Date: Tue, 29 Sep 2020 17:22:53 +0300 Subject: [PATCH] Propagate check_hostname option across the collection --- plugins/modules/mysql_db.py | 61 ++++++++-------- plugins/modules/mysql_info.py | 2 + plugins/modules/mysql_query.py | 9 ++- plugins/modules/mysql_replication.py | 69 +++++++++---------- plugins/modules/mysql_user.py | 55 +++++++-------- plugins/modules/mysql_variables.py | 28 +++----- .../targets/setup_mysql/vars/main.yml | 1 - .../tasks/config_overrides_defaults.yml | 2 +- .../tasks/mysql_replication_initial.yml | 5 ++ .../test_mysql_user/tasks/issue-28.yml | 16 ++--- 10 files changed, 114 insertions(+), 134 deletions(-) diff --git a/plugins/modules/mysql_db.py b/plugins/modules/mysql_db.py index 330a81f..814af4e 100644 --- a/plugins/modules/mysql_db.py +++ b/plugins/modules/mysql_db.py @@ -318,7 +318,7 @@ import traceback from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.mysql.plugins.module_utils.database import mysql_quote_identifier -from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg +from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils._text import to_native @@ -543,37 +543,30 @@ def db_create(cursor, db, encoding, collation): def main(): + argument_spec = mysql_common_argument_spec() + argument_spec.update( + name=dict(type='list', required=True, aliases=['db']), + encoding=dict(type='str', default=''), + collation=dict(type='str', default=''), + target=dict(type='path'), + state=dict(type='str', default='present', choices=['absent', 'dump', 'import', 'present']), + single_transaction=dict(type='bool', default=False), + quick=dict(type='bool', default=True), + ignore_tables=dict(type='list', default=[]), + hex_blob=dict(default=False, type='bool'), + force=dict(type='bool', default=False), + master_data=dict(type='int', default=0, choices=[0, 1, 2]), + skip_lock_tables=dict(type='bool', default=False), + dump_extra_args=dict(type='str'), + use_shell=dict(type='bool', default=False), + unsafe_login_password=dict(type='bool', default=False), + restrict_config_file=dict(type='bool', default=False), + check_implicit_admin=dict(type='bool', default=False), + config_overrides_defaults=dict(type='bool', default=False), + ) + module = AnsibleModule( - argument_spec=dict( - login_user=dict(type='str'), - login_password=dict(type='str', no_log=True), - login_host=dict(type='str', default='localhost'), - login_port=dict(type='int', default=3306), - login_unix_socket=dict(type='str'), - name=dict(type='list', required=True, aliases=['db']), - encoding=dict(type='str', default=''), - collation=dict(type='str', default=''), - target=dict(type='path'), - state=dict(type='str', default='present', choices=['absent', 'dump', 'import', 'present']), - client_cert=dict(type='path', aliases=['ssl_cert']), - client_key=dict(type='path', aliases=['ssl_key']), - ca_cert=dict(type='path', aliases=['ssl_ca']), - connect_timeout=dict(type='int', default=30), - config_file=dict(type='path', default='~/.my.cnf'), - single_transaction=dict(type='bool', default=False), - quick=dict(type='bool', default=True), - ignore_tables=dict(type='list', default=[]), - hex_blob=dict(default=False, type='bool'), - force=dict(type='bool', default=False), - master_data=dict(type='int', default=0, choices=[0, 1, 2]), - skip_lock_tables=dict(type='bool', default=False), - dump_extra_args=dict(type='str'), - use_shell=dict(type='bool', default=False), - unsafe_login_password=dict(type='bool', default=False, no_log=True), - restrict_config_file=dict(type='bool', default=False), - check_implicit_admin=dict(type='bool', default=False), - config_overrides_defaults=dict(type='bool', default=False), - ), + argument_spec=argument_spec, supports_check_mode=True, ) @@ -596,6 +589,7 @@ def main(): ssl_cert = module.params["client_cert"] ssl_key = module.params["client_key"] ssl_ca = module.params["ca_cert"] + check_hostname = module.params["check_hostname"] connect_timeout = module.params['connect_timeout'] config_file = module.params['config_file'] login_password = module.params["login_password"] @@ -636,7 +630,7 @@ def main(): if check_implicit_admin: try: cursor, db_conn = mysql_connect(module, 'root', '', config_file, ssl_cert, ssl_key, ssl_ca, - connect_timeout=connect_timeout, + connect_timeout=connect_timeout, check_hostname=check_hostname, config_overrides_defaults=config_overrides_defaults) except Exception as e: check_implicit_admin = False @@ -644,7 +638,8 @@ def main(): 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) + 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. " diff --git a/plugins/modules/mysql_info.py b/plugins/modules/mysql_info.py index 2259078..6dc0853 100644 --- a/plugins/modules/mysql_info.py +++ b/plugins/modules/mysql_info.py @@ -509,6 +509,7 @@ def main(): ssl_cert = module.params['client_cert'] ssl_key = module.params['client_key'] ssl_ca = module.params['ca_cert'] + check_hostname = module.params['check_hostname'] config_file = module.params['config_file'] filter_ = module.params['filter'] exclude_fields = module.params['exclude_fields'] @@ -526,6 +527,7 @@ def main(): 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') 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_query.py b/plugins/modules/mysql_query.py index 5dad74e..0101c20 100644 --- a/plugins/modules/mysql_query.py +++ b/plugins/modules/mysql_query.py @@ -144,6 +144,7 @@ def main(): ssl_cert = module.params['client_cert'] ssl_key = module.params['client_key'] ssl_ca = module.params['ca_cert'] + check_hostname = module.params['check_hostname'] config_file = module.params['config_file'] query = module.params["query"] if module.params["single_transaction"]: @@ -165,12 +166,14 @@ def main(): 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) 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))) + # Set defaults: changed = False @@ -210,7 +213,11 @@ def main(): if keyword in q: changed = True - executed_queries.append(cursor._last_executed) + try: + executed_queries.append(cursor._last_executed) + except AttributeError: + # MySQLdb removed cursor._last_executed as a duplicate of cursor._executed + executed_queries.append(cursor._executed) rowcount.append(cursor.rowcount) # When the module run with the single_transaction == True: diff --git a/plugins/modules/mysql_replication.py b/plugins/modules/mysql_replication.py index beaa2fc..9fb2a35 100644 --- a/plugins/modules/mysql_replication.py +++ b/plugins/modules/mysql_replication.py @@ -238,7 +238,7 @@ import os import warnings from ansible.module_utils.basic import AnsibleModule -from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg +from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec from ansible.module_utils._text import to_native executed_queries = [] @@ -381,43 +381,35 @@ def changemaster(cursor, chm, connection_name='', channel=''): def main(): + argument_spec = mysql_common_argument_spec() + argument_spec.update( + mode=dict(type='str', default='getslave', choices=[ + 'getmaster', 'getslave', 'changemaster', 'stopslave', + 'startslave', 'resetmaster', 'resetslave', 'resetslaveall']), + master_auto_position=dict(type='bool', default=False), + master_host=dict(type='str'), + master_user=dict(type='str'), + master_password=dict(type='str', no_log=True), + master_port=dict(type='int'), + master_connect_retry=dict(type='int'), + master_log_file=dict(type='str'), + master_log_pos=dict(type='int'), + relay_log_file=dict(type='str'), + relay_log_pos=dict(type='int'), + master_ssl=dict(type='bool', default=False), + master_ssl_ca=dict(type='str'), + master_ssl_capath=dict(type='str'), + master_ssl_cert=dict(type='str'), + master_ssl_key=dict(type='str'), + master_ssl_cipher=dict(type='str'), + master_use_gtid=dict(type='str', choices=['current_pos', 'slave_pos', 'disabled']), + master_delay=dict(type='int'), + connection_name=dict(type='str'), + channel=dict(type='str'), + fail_on_error=dict(type='bool', default=False), + ) module = AnsibleModule( - argument_spec=dict( - login_user=dict(type='str'), - login_password=dict(type='str', no_log=True), - login_host=dict(type='str', default='localhost'), - login_port=dict(type='int', default=3306), - login_unix_socket=dict(type='str'), - mode=dict(type='str', default='getslave', choices=[ - 'getmaster', 'getslave', 'changemaster', 'stopslave', - 'startslave', 'resetmaster', 'resetslave', 'resetslaveall']), - master_auto_position=dict(type='bool', default=False), - master_host=dict(type='str'), - master_user=dict(type='str'), - master_password=dict(type='str', no_log=True), - master_port=dict(type='int'), - master_connect_retry=dict(type='int'), - master_log_file=dict(type='str'), - master_log_pos=dict(type='int'), - relay_log_file=dict(type='str'), - relay_log_pos=dict(type='int'), - master_ssl=dict(type='bool', default=False), - master_ssl_ca=dict(type='str'), - master_ssl_capath=dict(type='str'), - master_ssl_cert=dict(type='str'), - master_ssl_key=dict(type='str'), - master_ssl_cipher=dict(type='str'), - connect_timeout=dict(type='int', default=30), - config_file=dict(type='path', default='~/.my.cnf'), - client_cert=dict(type='path', aliases=['ssl_cert']), - client_key=dict(type='path', aliases=['ssl_key']), - ca_cert=dict(type='path', aliases=['ssl_ca']), - master_use_gtid=dict(type='str', choices=['current_pos', 'slave_pos', 'disabled']), - master_delay=dict(type='int'), - connection_name=dict(type='str'), - channel=dict(type='str'), - fail_on_error=dict(type='bool', default=False), - ), + argument_spec=argument_spec, mutually_exclusive=[ ['connection_name', 'channel'] ], @@ -442,6 +434,7 @@ def main(): ssl_cert = module.params["client_cert"] ssl_key = module.params["client_key"] ssl_ca = module.params["ca_cert"] + check_hostname = module.params["check_hostname"] connect_timeout = module.params['connect_timeout'] config_file = module.params['config_file'] master_delay = module.params['master_delay'] @@ -464,7 +457,7 @@ def main(): try: cursor, db_conn = mysql_connect(module, login_user, login_password, config_file, ssl_cert, ssl_key, ssl_ca, None, cursor_class='DictCursor', - connect_timeout=connect_timeout) + 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 login_password are correct or %s has the credentials. " diff --git a/plugins/modules/mysql_user.py b/plugins/modules/mysql_user.py index 2cdc6a4..c5b5b09 100644 --- a/plugins/modules/mysql_user.py +++ b/plugins/modules/mysql_user.py @@ -297,7 +297,7 @@ import string from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.mysql.plugins.module_utils.database import SQLParseError -from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg +from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native @@ -996,35 +996,27 @@ def limit_resources(module, cursor, user, host, resource_limits, check_mode): def main(): + argument_spec = mysql_common_argument_spec() + argument_spec.update( + user=dict(type='str', required=True, aliases=['name']), + password=dict(type='str', no_log=True), + encrypted=dict(type='bool', default=False), + host=dict(type='str', default='localhost'), + host_all=dict(type="bool", default=False), + state=dict(type='str', default='present', choices=['absent', 'present']), + priv=dict(type='raw'), + tls_requires=dict(type='dict'), + append_privs=dict(type='bool', default=False), + check_implicit_admin=dict(type='bool', default=False), + update_password=dict(type='str', default='always', choices=['always', 'on_create'], no_log=False), + sql_log_bin=dict(type='bool', default=True), + plugin=dict(default=None, type='str'), + plugin_hash_string=dict(default=None, type='str'), + plugin_auth_string=dict(default=None, type='str'), + resource_limits=dict(type='dict'), + ) module = AnsibleModule( - argument_spec=dict( - login_user=dict(type='str'), - login_password=dict(type='str', no_log=True), - login_host=dict(type='str', default='localhost'), - login_port=dict(type='int', default=3306), - login_unix_socket=dict(type='str'), - user=dict(type='str', required=True, aliases=['name']), - password=dict(type='str', no_log=True), - encrypted=dict(type='bool', default=False), - host=dict(type='str', default='localhost'), - host_all=dict(type="bool", default=False), - state=dict(type='str', default='present', choices=['absent', 'present']), - priv=dict(type='raw'), - tls_requires=dict(type='dict'), - append_privs=dict(type='bool', default=False), - check_implicit_admin=dict(type='bool', default=False), - update_password=dict(type='str', default='always', choices=['always', 'on_create'], no_log=False), - connect_timeout=dict(type='int', default=30), - config_file=dict(type='path', default='~/.my.cnf'), - sql_log_bin=dict(type='bool', default=True), - client_cert=dict(type='path', aliases=['ssl_cert']), - client_key=dict(type='path', aliases=['ssl_key']), - ca_cert=dict(type='path', aliases=['ssl_ca']), - plugin=dict(default=None, type='str'), - plugin_hash_string=dict(default=None, type='str'), - plugin_auth_string=dict(default=None, type='str'), - resource_limits=dict(type='dict'), - ), + argument_spec=argument_spec, supports_check_mode=True, ) login_user = module.params["login_user"] @@ -1045,6 +1037,7 @@ def main(): ssl_cert = module.params["client_cert"] ssl_key = module.params["client_key"] ssl_ca = module.params["ca_cert"] + check_hostname = module.params["check_hostname"] db = '' sql_log_bin = module.params["sql_log_bin"] plugin = module.params["plugin"] @@ -1065,13 +1058,13 @@ def main(): 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) + 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) + 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 cf30e80..1b3418f 100644 --- a/plugins/modules/mysql_variables.py +++ b/plugins/modules/mysql_variables.py @@ -82,7 +82,7 @@ from re import match from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.mysql.plugins.module_utils.database import SQLParseError, mysql_quote_identifier -from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg +from ansible_collections.community.mysql.plugins.module_utils.mysql import mysql_connect, mysql_driver, mysql_driver_fail_msg, mysql_common_argument_spec from ansible.module_utils._text import to_native executed_queries = [] @@ -168,22 +168,15 @@ def setvariable(cursor, mysqlvar, value, mode='global'): def main(): + argument_spec = mysql_common_argument_spec() + argument_spec.update( + variable=dict(type='str'), + value=dict(type='str'), + mode=dict(type='str', choices=['global', 'persist', 'persist_only'], default='global'), + ) + module = AnsibleModule( - argument_spec=dict( - login_user=dict(type='str'), - login_password=dict(type='str', no_log=True), - login_host=dict(type='str', default='localhost'), - login_port=dict(type='int', default=3306), - login_unix_socket=dict(type='str'), - variable=dict(type='str'), - value=dict(type='str'), - client_cert=dict(type='path', aliases=['ssl_cert']), - client_key=dict(type='path', aliases=['ssl_key']), - ca_cert=dict(type='path', aliases=['ssl_ca']), - connect_timeout=dict(type='int', default=30), - config_file=dict(type='path', default='~/.my.cnf'), - mode=dict(type='str', choices=['global', 'persist', 'persist_only'], default='global'), - ), + argument_spec=argument_spec ) user = module.params["login_user"] password = module.params["login_password"] @@ -191,6 +184,7 @@ def main(): ssl_cert = module.params["client_cert"] ssl_key = module.params["client_key"] ssl_ca = module.params["ca_cert"] + check_hostname = module.params["check_hostname"] config_file = module.params['config_file'] db = 'mysql' @@ -209,7 +203,7 @@ def main(): try: cursor, db_conn = mysql_connect(module, user, password, config_file, ssl_cert, ssl_key, ssl_ca, db, - connect_timeout=connect_timeout) + 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 " diff --git a/tests/integration/targets/setup_mysql/vars/main.yml b/tests/integration/targets/setup_mysql/vars/main.yml index c71545d..e267307 100644 --- a/tests/integration/targets/setup_mysql/vars/main.yml +++ b/tests/integration/targets/setup_mysql/vars/main.yml @@ -15,7 +15,6 @@ percona_mysql_packages: - percona-server-client-{{ percona_client_version }} python_packages: [pymysql == 0.9.3] - # - mysqlclient == 2.0.1 # temporary fix pinning to 0.9.3 to ensure warnings are handled (https://github.com/ansible-collections/community.mysql/pull/9#issuecomment-663040948) install_prereqs: - libaio1 diff --git a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml index 422fba3..ef4c062 100644 --- a/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml +++ b/tests/integration/targets/test_mysql_db/tasks/config_overrides_defaults.yml @@ -71,7 +71,7 @@ assert: that: - result is failed - - result.msg is search("Can't connect to MySQL server on '{{ fake_host }}'") + - result.msg is search("Can't connect to MySQL server on '{{ fake_host }}'") or result.msg is search("Unknown MySQL server host '{{ fake_host }}'") # Clean up - name: Remove test db diff --git a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml index 632bd97..eb1b51a 100644 --- a/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml +++ b/tests/integration/targets/test_mysql_replication/tasks/mysql_replication_initial.yml @@ -165,6 +165,9 @@ that: - slave_status.Exec_Master_Log_Pos != mysql_primary_status.Position + - shell: pip show pymysql | awk '/Version/ {print $2}' + register: pymysql_version + - name: Start slave that is already running mysql_replication: <<: *mysql_params @@ -176,6 +179,7 @@ - assert: that: - result is not changed + when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=') # Test stopslave mode: - name: Stop slave @@ -202,3 +206,4 @@ - assert: that: - result is not changed + when: (pymysql_version.stdout | default('1000', true)) is version('0.9.3', '<=') diff --git a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml index 6d36721..d010ab4 100644 --- a/tests/integration/targets/test_mysql_user/tasks/issue-28.yml +++ b/tests/integration/targets/test_mysql_user/tasks/issue-28.yml @@ -9,6 +9,9 @@ block: # ============================================================ + - shell: pip show pymysql | awk '/Version/ {print $2}' + register: pymysql_version + - name: get server certificate copy: content: "{{ lookup('pipe', \"openssl s_client -starttls mysql -connect localhost:3307 -showcerts 2>/dev/null