Add support for MariaDB 11.4 (#703)

* fix missing symlink to mysql binaries for MariaDB 11+

* update tested version of MariaDB 11.4 instead of 10.5

* add changelog fragment

* [CI] add way to trigger workflow manually

Useful in the case we don't modifiy any files in the paths: sections of the push event.

* add version check for mariadb < 10.4.6 without mariadb* binaries

* Use same concatenation method between functions to avoid future confusion

I didn't notice that db_dump and db_import were different, thus I introduced a bug with the initialization of the variable cmd. This commit fixes that.
This commit is contained in:
Laurent Indermühle 2025-03-10 18:55:42 +01:00 committed by GitHub
parent e9845b0a1c
commit dd7e297d50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 84 additions and 49 deletions

View file

@ -13,7 +13,7 @@ on: # yamllint disable-line rule:truthy
- '.github/workflows/ansible-test-plugins.yml'
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
jobs:
sanity:
@ -54,8 +54,8 @@ jobs:
db_engine_version:
- '8.0.38'
- '8.4.1'
- '10.5.25'
- '10.11.8'
- '11.4.5'
connector_name:
- pymysql
- mysqlclient
@ -87,10 +87,10 @@ jobs:
exclude:
- db_engine_name: mysql
db_engine_version: '10.5.25'
db_engine_version: '10.11.8'
- db_engine_name: mysql
db_engine_version: '10.11.8'
db_engine_version: '11.4.5'
- db_engine_name: mariadb
db_engine_version: '8.0.38'
@ -119,13 +119,13 @@ jobs:
- db_engine_version: '8.0.38'
ansible: stable-2.17
- db_engine_version: '10.5.25'
- db_engine_version: '10.11.8'
ansible: stable-2.17
- db_engine_version: '8.0.38'
ansible: devel
- db_engine_version: '10.5.25'
- db_engine_version: '10.11.8'
ansible: devel
- db_engine_version: '8.4.1'
@ -162,7 +162,7 @@ jobs:
db_engine_version: '8.0.38'
- connector_version: '1.1.1'
db_engine_version: '10.5.25'
db_engine_version: '10.11.8'
services:
db_primary:
@ -175,7 +175,7 @@ jobs:
# We write our own health-cmd because the mariadb container does not
# provide a healthcheck
options: >-
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-start-period 10s
--health-interval 10s
--health-timeout 5s
@ -189,7 +189,7 @@ jobs:
ports:
- 3308:3306
options: >-
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-start-period 10s
--health-interval 10s
--health-timeout 5s
@ -203,7 +203,7 @@ jobs:
ports:
- 3309:3306
options: >-
--health-cmd "mysqladmin ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-cmd "${{ matrix.db_engine_name == 'mysql' && 'mysqladmin' || 'mariadb-admin' }} ping -P 3306 -pmsandbox |grep alive || exit 1"
--health-start-period 10s
--health-interval 10s
--health-timeout 5s

View file

@ -11,6 +11,17 @@ ifdef continue_on_errors
_continue_on_errors = --continue-on-error
endif
# Set command variables based on database engine
# Required for MariaDB 11+ which no longer includes mysql named compatible
# executable symlinks
ifeq ($(db_engine_name),mysql)
_command = mysqld
_health_cmd = mysqladmin
else
_command = mariadbd
_health_cmd = mariadb-admin
endif
.PHONY: test-integration
test-integration:
@echo -n $(db_engine_name) > tests/integration/db_engine_name
@ -29,9 +40,9 @@ test-integration:
--env MYSQL_ROOT_PASSWORD=msandbox \
--network podman \
--publish 3307:3306 \
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
docker.io/library/$(db_engine_name):$(db_engine_version) \
mysqld
$(_command)
podman run \
--detach \
--replace \
@ -40,9 +51,9 @@ test-integration:
--env MYSQL_ROOT_PASSWORD=msandbox \
--network podman \
--publish 3308:3306 \
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
docker.io/library/$(db_engine_name):$(db_engine_version) \
mysqld
$(_command)
podman run \
--detach \
--replace \
@ -51,9 +62,9 @@ test-integration:
--env MYSQL_ROOT_PASSWORD=msandbox \
--network podman \
--publish 3309:3306 \
--health-cmd 'mysqladmin ping -P 3306 -pmsandbox | grep alive || exit 1' \
--health-cmd '$(_health_cmd) ping -P 3306 -pmsandbox | grep alive || exit 1' \
docker.io/library/$(db_engine_name):$(db_engine_version) \
mysqld
$(_command)
# Setup replication and restart containers using the same subshell to keep variables alive
db_ver=$(db_engine_version); \
maj="$${db_ver%.*.*}"; \

View file

@ -112,10 +112,10 @@ For MariaDB, only Long Term releases are tested. When multiple LTS are available
- mariadb:10.3.34 (collection version < 3.5.1)
- mariadb:10.4.24 (collection version >= 3.5.2, < 3.10.0)
- mariadb:10.5.18 (collection version >= 3.5.2, < 3.10.0)
- mariadb:10.5.25 (collection version >= 3.10.0)
- mariadb:10.5.25 (collection version >= 3.10.0, <3.13.0)
- mariadb:10.6.11 (collection version >= 3.5.2, < 3.10.0)
- mariadb:10.11.8 (collection version >= 3.10.0)
- mariadb:11.4.5 (collection version >= 3.13.0)
### Database connectors

View file

@ -65,8 +65,8 @@ The Makefile accept the following options
- Choices:
- "8.0.38" <- mysql
- "8.4.1" <- mysql (NOT WORKING YET, ansible-test uses Ubuntu 20.04 which is too old to install mysql-community-client 8.4)
- "10.5.25" <- mariadb
- "10.11.8" <- mariadb
- "11.4.5" <- mariadb
- Description: The tag of the container to use for the service containers that will host a primary database and two replicas. Do not use short version, like `mysql:8` (don't do that) because our tests expect a full version to filter tests precisely. For instance: `when: db_version is version ('8.0.22', '>')`. You can use any tag available on [hub.docker.com/_/mysql](https://hub.docker.com/_/mysql) and [hub.docker.com/_/mariadb](https://hub.docker.com/_/mariadb) but GitHub Action will only use the versions listed above.
- `connector_name`
@ -121,7 +121,7 @@ make ansible="stable-2.16" db_engine_name="mysql" db_engine_version="8.0.31" con
make ansible="stable-2.17" db_engine_name="mysql" db_engine_version="8.0.31" connector_name="mysqlclient" connector_version="2.0.3" target="test_mysql_query" keep_containers_alive=1 continue_on_errors=1
# If your system has an usupported version of Python:
make local_python_version="3.10" ansible="stable-2.17" db_engine_name="mariadb" db_engine_version="10.6.11" connector_name="pymysql" connector_version="1.0.2"
make local_python_version="3.10" ansible="stable-2.17" db_engine_name="mariadb" db_engine_version="11.4.5" connector_name="pymysql" connector_version="1.0.2"
```

View file

@ -0,0 +1,5 @@
---
minor_changes:
- Integration tests for MariaDB 11.4 have replaced those for 10.5. The previous version is now 10.11.
bugfixes:
- mysql_db - fix dump and import to find MariaDB binaries (mariadb and mariadb-dump) when MariaDB 11+ is used and symbolic links to MySQL binaries are absent.

View file

@ -386,67 +386,75 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port,
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, pipefail=False):
cmd = module.get_bin_path('mysqldump', True)
cmd_str = 'mysqldump'
if server_implementation == 'mariadb' and LooseVersion(server_version) >= LooseVersion("10.4.6"):
cmd_str = 'mariadb-dump'
try:
cmd = [module.get_bin_path(cmd_str, True)]
except Exception as e:
return 1, "", "Error determining dump command: %s" % str(e)
# If defined, mysqldump demands --defaults-extra-file be the first option
if config_file:
if restrict_config_file:
cmd += " --defaults-file=%s" % shlex_quote(config_file)
cmd.append("--defaults-file=%s" % shlex_quote(config_file))
else:
cmd += " --defaults-extra-file=%s" % shlex_quote(config_file)
cmd.append("--defaults-extra-file=%s" % shlex_quote(config_file))
if check_implicit_admin:
cmd += " --user=root --password=''"
cmd.append("--user=root --password=''")
else:
if user is not None:
cmd += " --user=%s" % shlex_quote(user)
cmd.append("--user=%s" % shlex_quote(user))
if password is not None:
if not unsafe_password:
cmd += " --password=%s" % shlex_quote(password)
cmd.append("--password=%s" % shlex_quote(password))
else:
cmd += " --password=%s" % password
cmd.append("--password=%s" % password)
if ssl_cert is not None:
cmd += " --ssl-cert=%s" % shlex_quote(ssl_cert)
cmd.append("--ssl-cert=%s" % shlex_quote(ssl_cert))
if ssl_key is not None:
cmd += " --ssl-key=%s" % shlex_quote(ssl_key)
cmd.append("--ssl-key=%s" % shlex_quote(ssl_key))
if ssl_ca is not None:
cmd += " --ssl-ca=%s" % shlex_quote(ssl_ca)
cmd.append("--ssl-ca=%s" % shlex_quote(ssl_ca))
if force:
cmd += " --force"
cmd.append("--force")
if socket is not None:
cmd += " --socket=%s" % shlex_quote(socket)
cmd.append("--socket=%s" % shlex_quote(socket))
else:
cmd += " --host=%s --port=%i" % (shlex_quote(host), port)
cmd.append("--host=%s --port=%i" % (shlex_quote(host), port))
if all_databases:
cmd += " --all-databases"
cmd.append("--all-databases")
elif len(db_name) > 1:
cmd += " --databases {0}".format(' '.join(db_name))
cmd.append("--databases {0}".format(' '.join(db_name)))
else:
cmd += " %s" % shlex_quote(' '.join(db_name))
cmd.append("%s" % shlex_quote(' '.join(db_name)))
if skip_lock_tables:
cmd += " --skip-lock-tables"
cmd.append("--skip-lock-tables")
if (encoding is not None) and (encoding != ""):
cmd += " --default-character-set=%s" % shlex_quote(encoding)
cmd.append("--default-character-set=%s" % shlex_quote(encoding))
if single_transaction:
cmd += " --single-transaction=true"
cmd.append("--single-transaction=true")
if quick:
cmd += " --quick"
cmd.append("--quick")
if ignore_tables:
for an_ignored_table in ignore_tables:
cmd += " --ignore-table={0}".format(an_ignored_table)
cmd.append("--ignore-table={0}".format(an_ignored_table))
if hex_blob:
cmd += " --hex-blob"
cmd.append("--hex-blob")
if master_data:
if (server_implementation == 'mysql' and
LooseVersion(server_version) >= LooseVersion("8.2.0")):
cmd += " --source-data=%s" % master_data
cmd.append("--source-data=%s" % master_data)
else:
cmd += " --master-data=%s" % master_data
cmd.append("--master-data=%s" % master_data)
if dump_extra_args is not None:
cmd += " " + dump_extra_args
cmd.append(dump_extra_args)
path = None
if os.path.splitext(target)[-1] == '.gz':
@ -458,6 +466,8 @@ def db_dump(module, host, user, password, db_name, target, all_databases, port,
elif os.path.splitext(target)[-1] == '.zst':
path = module.get_bin_path('zstd', True)
cmd = ' '.join(cmd)
if path:
cmd = '%s | %s > %s' % (cmd, path, shlex_quote(target))
if pipefail:
@ -476,13 +486,21 @@ 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,
server_implementation, server_version, 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):
if not os.path.exists(target):
return module.fail_json(msg="target %s does not exist on the host" % target)
cmd = [module.get_bin_path('mysql', True)]
cmd_str = 'mysql'
if server_implementation == 'mariadb' and LooseVersion(server_version) >= LooseVersion("10.4.6"):
cmd_str = 'mariadb'
try:
cmd = [module.get_bin_path(cmd_str, True)]
except Exception as e:
return 1, "", "Error determining mysql/mariadb command: %s" % str(e)
# --defaults-file must go first, or errors out
if config_file:
if restrict_config_file:
@ -772,8 +790,8 @@ def main():
rc, stdout, stderr = db_import(module, login_host, login_user,
login_password, db, target,
all_databases,
login_port, config_file,
socket, ssl_cert, ssl_key, ssl_ca,
login_port, config_file, server_implementation,
server_version, socket, ssl_cert, ssl_key, ssl_ca,
encoding, force, use_shell, unsafe_login_password,
restrict_config_file, check_implicit_admin)
if rc != 0:

View file

@ -4,6 +4,7 @@
# Copyright: (c) 2019, Andrew Klychkov (@Andersson007) <andrew.a.klychkov@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type