|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8; py-indent-offset: 4 -*- |
| 3 | +# |
| 4 | +# Author: Linuxfabrik GmbH, Zurich, Switzerland |
| 5 | +# Contact: info (at) linuxfabrik (dot) ch |
| 6 | +# https://www.linuxfabrik.ch/ |
| 7 | +# License: The Unlicense, see LICENSE file. |
| 8 | + |
| 9 | +# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md |
| 10 | + |
| 11 | +"""Integration tests for the mysql-storage-engines check plugin. |
| 12 | +
|
| 13 | +The plugin opens a real `pymysql` connection and introspects |
| 14 | +`information_schema.tables`, `SHOW ENGINES`, `SHOW VARIABLES` and |
| 15 | +`SHOW DATABASES`, so a static fixture cannot drive it - we spin up |
| 16 | +an actual MariaDB server and let the plugin talk to it over TCP. |
| 17 | +
|
| 18 | +Container source: `quay.io/sclorg/mariadb-1011-c10s` - the Red Hat / |
| 19 | +CentOS Stream 10 sclorg packaging of MariaDB 10.11 LTS. |
| 20 | +
|
| 21 | +Per CONTRIBUTING's "Combine container tests with fixtures" rule, |
| 22 | +this file holds only the happy-path integration test. We seed the |
| 23 | +container's `test` DB with one empty InnoDB table so the plugin sees |
| 24 | +at least one table on the default engine - otherwise it would warn |
| 25 | +"InnoDB is enabled but isn't being used. Add skip-innodb to ...". |
| 26 | +
|
| 27 | +Requirements: |
| 28 | +- podman (or docker) with a reachable socket |
| 29 | +- `pip install testcontainers` |
| 30 | +- `tools/run-unit-tests` auto-sets `CONTAINER_HOST` and |
| 31 | + `TESTCONTAINERS_RYUK_DISABLED` |
| 32 | +""" |
| 33 | + |
| 34 | +import os |
| 35 | +import subprocess |
| 36 | +import sys |
| 37 | +import tempfile |
| 38 | +import unittest |
| 39 | + |
| 40 | +sys.path.insert(0, '..') |
| 41 | + |
| 42 | +import lib.lftest |
| 43 | +from lib.globals import STATE_OK |
| 44 | + |
| 45 | + |
| 46 | +IMAGES = [ |
| 47 | + ('quay.io/sclorg/mariadb-1011-c10s', 'MariaDB 10.11'), |
| 48 | +] |
| 49 | + |
| 50 | + |
| 51 | +class TestCheck(unittest.TestCase): |
| 52 | + pass |
| 53 | + |
| 54 | + |
| 55 | +def _check_image(test, image_pair): |
| 56 | + image, label = image_pair |
| 57 | + print(f'\n=== Testing {label} ({image}) ===', flush=True) |
| 58 | + with lib.lftest.run_container( |
| 59 | + image, |
| 60 | + env={ |
| 61 | + 'MYSQL_ROOT_PASSWORD': 'test', |
| 62 | + 'MYSQL_USER': 'test', |
| 63 | + 'MYSQL_PASSWORD': 'test', |
| 64 | + 'MYSQL_DATABASE': 'test', |
| 65 | + }, |
| 66 | + ports=[3306], |
| 67 | + command='run-mysqld --port=3306', |
| 68 | + wait_log='port: 3306', |
| 69 | + wait_log_timeout=180, |
| 70 | + ) as container: |
| 71 | + host = container.get_container_host_ip() |
| 72 | + port = container.get_exposed_port(3306) |
| 73 | + |
| 74 | + # Seed an empty InnoDB table so the plugin sees the default |
| 75 | + # storage engine "in use" and does not warn about it. |
| 76 | + container.exec([ |
| 77 | + 'sh', '-c', |
| 78 | + 'mysql -utest -ptest test -e ' |
| 79 | + '"CREATE TABLE seed_innodb (id INT PRIMARY KEY) ENGINE=InnoDB"', |
| 80 | + ]) |
| 81 | + |
| 82 | + with tempfile.NamedTemporaryFile( |
| 83 | + mode='w', |
| 84 | + suffix='.cnf', |
| 85 | + delete=False, |
| 86 | + ) as cnf: |
| 87 | + cnf.write( |
| 88 | + f'[client]\n' |
| 89 | + f'host={host}\n' |
| 90 | + f'port={port}\n' |
| 91 | + f'user=test\n' |
| 92 | + f'password=test\n' |
| 93 | + f'database=test\n' |
| 94 | + ) |
| 95 | + defaults_file = cnf.name |
| 96 | + |
| 97 | + try: |
| 98 | + cmd = [ |
| 99 | + 'python3', '../mysql-storage-engines', |
| 100 | + f'--defaults-file={defaults_file}', |
| 101 | + ] |
| 102 | + print(f'Run plugin: {" ".join(cmd)}', flush=True) |
| 103 | + result = subprocess.run( |
| 104 | + cmd, |
| 105 | + cwd=os.path.dirname(os.path.abspath(__file__)), |
| 106 | + capture_output=True, |
| 107 | + text=True, |
| 108 | + ) |
| 109 | + finally: |
| 110 | + os.unlink(defaults_file) |
| 111 | + |
| 112 | + combined = result.stdout + result.stderr |
| 113 | + print(f'Script output:\n{combined.strip()}', flush=True) |
| 114 | + |
| 115 | + # A freshly booted server has no user tables, so the plugin |
| 116 | + # finds no fragmented tables, no auto-increment hotspots and |
| 117 | + # no unused storage engines to recommend disabling. |
| 118 | + test.assertEqual(result.returncode, STATE_OK) |
| 119 | + test.assertIn('Everything is ok.', combined) |
| 120 | + |
| 121 | + |
| 122 | +lib.lftest.attach_each(TestCheck, IMAGES, _check_image, id_func=lambda it: it[1]) |
| 123 | + |
| 124 | + |
| 125 | +if __name__ == '__main__': |
| 126 | + unittest.main() |
0 commit comments