|
13 | 13 | import contextlib |
14 | 14 | import os |
15 | 15 | import re |
| 16 | +import tempfile |
16 | 17 |
|
17 | 18 | from . import base, disk, shell |
18 | 19 |
|
19 | 20 | __author__ = 'Linuxfabrik GmbH, Zurich/Switzerland' |
20 | | -__version__ = '2026041303' |
| 21 | +__version__ = '2026041305' |
| 22 | + |
| 23 | + |
| 24 | +# Shared IMAGES matrix for mysql-* container tests. Covers the |
| 25 | +# currently supported MariaDB LTS releases across the Red Hat family |
| 26 | +# (sclorg quay.io images) and the upstream Debian-based image: |
| 27 | +# |
| 28 | +# - 10.6: oldest still-supported LTS (EOL 2026-07), upstream only |
| 29 | +# - 10.11: current workhorse LTS (EOL 2028-02), sclorg c10s |
| 30 | +# - 11.4: newer LTS (EOL 2029-05), upstream only - sclorg does not |
| 31 | +# publish a 11.4 image |
| 32 | +# - 11.8: newest LTS (EOL 2030-06), sclorg c10s |
| 33 | +# |
| 34 | +# All 16 mysql-* container tests in the repo iterate over this list |
| 35 | +# so adding a new LTS release (or retiring one that reaches EOL) is |
| 36 | +# a single-line change across the whole test suite. |
| 37 | +MARIADB_LTS_IMAGES = [ |
| 38 | + ('docker.io/library/mariadb:10.6', 'MariaDB 10.6'), |
| 39 | + ('quay.io/sclorg/mariadb-1011-c10s', 'MariaDB 10.11 sclorg'), |
| 40 | + ('docker.io/library/mariadb:11.4', 'MariaDB 11.4'), |
| 41 | + ('quay.io/sclorg/mariadb-118-c10s', 'MariaDB 11.8 sclorg'), |
| 42 | +] |
21 | 43 |
|
22 | 44 |
|
23 | 45 | def run(test_instance, plugin, testcase): |
@@ -319,6 +341,121 @@ def run_container( |
319 | 341 | c.stop() |
320 | 342 |
|
321 | 343 |
|
| 344 | +@contextlib.contextmanager |
| 345 | +def run_mariadb(image, *, extra_args=None, seed=None): |
| 346 | + """Start a MariaDB container and yield (container, defaults_file). |
| 347 | +
|
| 348 | + Thin convenience wrapper around :func:`run_container` for the |
| 349 | + Linuxfabrik mysql-* check plugins. Hides the image-family |
| 350 | + boilerplate (env vars, TCP port exposure, start command, log |
| 351 | + marker to wait on) and writes a temporary `[client]` `.cnf` file |
| 352 | + pointing at the exposed host port so the caller can run a plugin |
| 353 | + with `--defaults-file=...` without manual tempfile management. |
| 354 | +
|
| 355 | + Supports two image families: |
| 356 | +
|
| 357 | + - **Red Hat family via sclorg** (`quay.io/sclorg/mariadb-*`). |
| 358 | + The sclorg entrypoint disables the TCP listener by default and |
| 359 | + binds only the unix socket, so the helper forces |
| 360 | + `run-mysqld --port=3306`. |
| 361 | + - **Upstream** (`docker.io/library/mariadb:*`). Uses the default |
| 362 | + `docker-entrypoint.sh` which already enables TCP on 3306; the |
| 363 | + helper only overrides the command when `extra_args` are given, |
| 364 | + in which case it appends them to `mariadbd`. |
| 365 | +
|
| 366 | + The `MYSQL_*` env var names work for both families (the upstream |
| 367 | + image accepts them as aliases for `MARIADB_*`). The log marker |
| 368 | + `port: 3306` appears in both startup banners once the TCP listener |
| 369 | + is bound, so the same wait works for both. |
| 370 | +
|
| 371 | + ### Parameters |
| 372 | + - **image** (`str`): MariaDB image reference, e.g. |
| 373 | + `'quay.io/sclorg/mariadb-1011-c10s'` or |
| 374 | + `'docker.io/library/mariadb:11.8'`. |
| 375 | + - **extra_args** (`str`, optional): Extra `mariadbd` flags appended |
| 376 | + to the startup command, e.g. |
| 377 | + `'--innodb-buffer-pool-size=33554432'` to pin the buffer pool to |
| 378 | + a deterministic size. |
| 379 | + - **seed** (`str`, optional): SQL statement executed once via |
| 380 | + `container.exec` right after the container is ready. Used to |
| 381 | + seed happy-path state (e.g. creating an empty InnoDB table so |
| 382 | + storage-engine checks see the engine "in use"). The helper |
| 383 | + auto-detects whether the image ships the `mariadb` client (11.x |
| 384 | + upstream dropped the `mysql` alias) or only `mysql` (older |
| 385 | + sclorg images) and picks whichever is available. |
| 386 | +
|
| 387 | + ### Yields |
| 388 | + - **tuple** (`DockerContainer`, `str`): |
| 389 | + - The running container (so callers can still reach |
| 390 | + `container.exec()`, `get_container_host_ip()` etc.). |
| 391 | + - Absolute path to a temporary `[client]` `.cnf` file that is |
| 392 | + deleted when the context manager exits. |
| 393 | +
|
| 394 | + ### Example |
| 395 | + >>> with lib.lftest.run_mariadb( |
| 396 | + ... 'docker.io/library/mariadb:11.8', |
| 397 | + ... extra_args='--innodb-buffer-pool-size=33554432', |
| 398 | + ... ) as (container, defaults_file): |
| 399 | + ... result = subprocess.run( |
| 400 | + ... ['python3', '../mysql-traffic', f'--defaults-file={defaults_file}'], |
| 401 | + ... capture_output=True, text=True, |
| 402 | + ... ) |
| 403 | + """ |
| 404 | + is_sclorg = 'sclorg/' in image |
| 405 | + |
| 406 | + if is_sclorg: |
| 407 | + cmd = 'run-mysqld --port=3306' |
| 408 | + if extra_args: |
| 409 | + cmd = f'{cmd} {extra_args}' |
| 410 | + else: |
| 411 | + cmd = f'mariadbd {extra_args}' if extra_args else None |
| 412 | + |
| 413 | + with run_container( |
| 414 | + image, |
| 415 | + env={ |
| 416 | + 'MYSQL_ROOT_PASSWORD': 'test', |
| 417 | + 'MYSQL_USER': 'test', |
| 418 | + 'MYSQL_PASSWORD': 'test', |
| 419 | + 'MYSQL_DATABASE': 'test', |
| 420 | + }, |
| 421 | + ports=[3306], |
| 422 | + command=cmd, |
| 423 | + wait_log='port: 3306', |
| 424 | + wait_log_timeout=180, |
| 425 | + ) as container: |
| 426 | + if seed: |
| 427 | + # 11.x upstream dropped the `mysql` client symlink in favor |
| 428 | + # of `mariadb`; sclorg c10s ships both. Prefer `mariadb`, |
| 429 | + # fall back to `mysql` so both families work. |
| 430 | + container.exec([ |
| 431 | + 'sh', '-c', |
| 432 | + 'if command -v mariadb >/dev/null 2>&1; then CLIENT=mariadb; ' |
| 433 | + 'else CLIENT=mysql; fi; ' |
| 434 | + f'"$CLIENT" -utest -ptest test -e "{seed}"', |
| 435 | + ]) |
| 436 | + |
| 437 | + host = container.get_container_host_ip() |
| 438 | + port = container.get_exposed_port(3306) |
| 439 | + |
| 440 | + fd, defaults_file = tempfile.mkstemp(suffix='.cnf') |
| 441 | + try: |
| 442 | + with os.fdopen(fd, 'w') as f: |
| 443 | + f.write( |
| 444 | + f'[client]\n' |
| 445 | + f'host={host}\n' |
| 446 | + f'port={port}\n' |
| 447 | + f'user=test\n' |
| 448 | + f'password=test\n' |
| 449 | + f'database=test\n' |
| 450 | + ) |
| 451 | + yield container, defaults_file |
| 452 | + finally: |
| 453 | + try: |
| 454 | + os.unlink(defaults_file) |
| 455 | + except OSError: |
| 456 | + pass |
| 457 | + |
| 458 | + |
322 | 459 | def test(args): |
323 | 460 | """ |
324 | 461 | Returns the content of two files and the provided return code. The first file represents STDOUT, |
|
0 commit comments