diff --git a/bci_tester/data.py b/bci_tester/data.py index 958d71a7..eb477d37 100755 --- a/bci_tester/data.py +++ b/bci_tester/data.py @@ -552,6 +552,25 @@ def create_BCI( PHP_8_APACHE = create_BCI(build_tag="bci/php-apache:8") PHP_8_FPM = create_BCI(build_tag="bci/php-fpm:8") +MARIADB_ROOT_PASSWORD = "n0ts3cr3t" + +MARIADB_CONTAINERS = [ + create_BCI( + build_tag=f"{APP_CONTAINER_PREFIX}/mariadb:{mariadb_ver}", + bci_type=ImageType.APPLICATION, + available_versions=maria_versions, + forwarded_ports=[PortForwarding(container_port=3306)], + extra_environment_variables={ + "MARIADB_ROOT_PASSWORD": MARIADB_ROOT_PASSWORD + }, + ) + for mariadb_ver, maria_versions in ( + ("10.6", ("15.5", "15.6")), + ("11.2", ("tumbleweed",)), + ) +] + + POSTGRES_PASSWORD = "n0ts3cr3t" POSTGRESQL_CONTAINERS = [ @@ -649,6 +668,7 @@ def create_BCI( + GOLANG_CONTAINERS + RUST_CONTAINERS + OPENJDK_CONTAINERS + + MARIADB_CONTAINERS + POSTGRESQL_CONTAINERS + (DOTNET_CONTAINERS if LOCALHOST.system_info.arch == "x86_64" else []) ) diff --git a/pyproject.toml b/pyproject.toml index 05f30c8c..de9aa7d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,8 @@ markers = [ 'golang_oldstable-openssl', 'golang_stable', 'golang_stable-openssl', + 'mariadb_10.6', + 'mariadb_11.2', 'nodejs_16', 'nodejs_18', 'nodejs_20', diff --git a/tests/test_all.py b/tests/test_all.py index 7649703c..3f19c121 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -21,6 +21,7 @@ from bci_tester.data import DISTRIBUTION_CONTAINER from bci_tester.data import INIT_CONTAINER from bci_tester.data import KERNEL_MODULE_CONTAINER +from bci_tester.data import MARIADB_CONTAINERS from bci_tester.data import OS_PRETTY_NAME from bci_tester.data import OS_VERSION from bci_tester.data import OS_VERSION_ID @@ -290,16 +291,15 @@ def test_zypper_verify_passes(container_per_test: ContainerData) -> None: for c in ALL_CONTAINERS if ( c - not in ( - [ - INIT_CONTAINER, - PCP_CONTAINER, - # kernel-module-container contains systemd due to pesign, - # fixes are pending - KERNEL_MODULE_CONTAINER, - ] - + POSTGRESQL_CONTAINERS - ) + not in [ + INIT_CONTAINER, + PCP_CONTAINER, + # kernel-module-container contains systemd due to pesign, + # fixes are pending + KERNEL_MODULE_CONTAINER, + *POSTGRESQL_CONTAINERS, + *MARIADB_CONTAINERS, + ] ) ], indirect=True, diff --git a/tests/test_mariadb.py b/tests/test_mariadb.py new file mode 100644 index 00000000..6e3c3f97 --- /dev/null +++ b/tests/test_mariadb.py @@ -0,0 +1,141 @@ +"""Tests for the MariaDB related application container images.""" +from itertools import product +from typing import List +from typing import Optional + +import pymysql +import pytest +from _pytest.mark import ParameterSet +from pytest_container.container import container_from_pytest_param +from pytest_container.container import ContainerData +from pytest_container.container import DerivedContainer +from tenacity import retry +from tenacity import stop_after_attempt +from tenacity import wait_exponential + +from bci_tester.data import MARIADB_CONTAINERS +from bci_tester.data import MARIADB_ROOT_PASSWORD + + +CONTAINER_IMAGES = MARIADB_CONTAINERS + + +def test_entry_point(auto_container: ContainerData) -> None: + # do really nothing here, just check that the container launched + assert auto_container.connection.run_expect([0], "ps") + + assert len(auto_container.inspect.config.entrypoint) == 1 + assert ( + "docker-entrypoint.sh" in auto_container.inspect.config.entrypoint[0] + ) + + +_other_db_user = "foo" +_other_db_pw = "baz" + +# TODO test variants +_test_db = "bcitest" + + +def _generate_test_matrix() -> List[ParameterSet]: + params = [] + + for db_cont_param in MARIADB_CONTAINERS: + db_cont = container_from_pytest_param(db_cont_param) + marks = db_cont_param.marks + ports = db_cont.forwarded_ports + for db_user, db_pw in product( + ("user", _other_db_user), (MARIADB_ROOT_PASSWORD, _other_db_pw) + ): + env = { + "MARIADB_USER": db_user, + "MARIADB_PASSWORD": db_pw, + "MARIADB_DATABASE": _test_db, + } + env["MARIADB_ROOT_PASSWORD"] = MARIADB_ROOT_PASSWORD + ### not supported by the container + # env["MARIADB_RANDOM_ROOT_PASSWORD"] = "1" + + params.append( + pytest.param( + DerivedContainer( + base=db_cont, + forwarded_ports=ports, + extra_environment_variables=env, + ), + db_user, + db_pw, + marks=marks, + ) + ) + + return params + + +@pytest.mark.parametrize( + "container_per_test,db_user,db_password", + _generate_test_matrix(), + indirect=["container_per_test"], +) +def test_mariadb_db_env_vars( + container_per_test: ContainerData, + db_user: str, + db_password: str, +) -> None: + """Simple smoke test connecting to the MariaDB database using the example + from ``_ while + setting the ``MARIADB_USER`` and ``MARIADB_PASSWORD`` environment + variables. + + """ + conn = None + cur = None + + dbdir = "/var/lib/mysql" + + dbdir_f = container_per_test.connection.file(dbdir) + assert dbdir_f.exists + # owner is root under docker and mysql under podman + # assert dbdir_f.user == "mysql" + assert dbdir_f.mode == 0o755 + + assert container_per_test.connection.check_output("id -un") == ("root") + + @retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + stop=stop_after_attempt(5), + ) + def wait_for_db_to_start(): + conn = pymysql.connect( + user=db_user, + password=db_password, + database=_test_db, + host="127.0.0.1", + port=container_per_test.forwarded_ports[0].host_port, + ) + with conn: + conn.ping(reconnect=False) + + # no healthcheck - https://mariadb.org/mariadb-server-docker-official-images-healthcheck-without-mysqladmin/ + wait_for_db_to_start() + + conn = pymysql.connect( + user=db_user, + password=db_password, + database=_test_db, + host="127.0.0.1", + port=container_per_test.forwarded_ports[0].host_port, + ) + with conn: + with conn.cursor() as cur: + cur.execute( + "CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar(32));" + ) + cur.execute( + "INSERT INTO test (num, data) VALUES (%s, %s)", + (100, "abc'def"), + ) + conn.commit() + with conn.cursor() as cur: + cur.execute("SELECT * FROM test;") + assert cur.fetchone() == (1, 100, "abc'def") diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 45c3f95a..efc4ad7f 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -43,6 +43,7 @@ from bci_tester.data import L3_CONTAINERS from bci_tester.data import LTSS_BASE_CONTAINERS from bci_tester.data import LTSS_BASE_FIPS_CONTAINERS +from bci_tester.data import MARIADB_CONTAINERS from bci_tester.data import MICRO_CONTAINER from bci_tester.data import MINIMAL_CONTAINER from bci_tester.data import NGINX_CONTAINER @@ -156,6 +157,16 @@ def _get_container_label_prefix( (golang_container, "golang", ImageType.LANGUAGE_STACK) for golang_container in GOLANG_CONTAINERS ] + + [ + ( + mariab_container, + "mariadb" + if OS_VERSION in ("basalt", "tumbleweed") + else "rmt-mariadb", + ImageType.APPLICATION, + ) + for mariab_container in MARIADB_CONTAINERS + ] + [ (pg_container, "postgres", ImageType.APPLICATION) for pg_container in POSTGRESQL_CONTAINERS diff --git a/tox.ini b/tox.ini index 509bd4ea..d2005aef 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = {py36,py39,py310,py311,py312}-unit, build, all, base, fips, init, dotnet, python, ruby, node, go, openjdk, openjdk_devel, rust, php, busybox, 389ds, metadata, minimal, multistage, repository, doc, lint, get_urls, pcp, distribution, postgres, git, helm, nginx, kernel_module +envlist = {py36,py39,py310,py311,py312}-unit, build, all, base, fips, init, dotnet, python, ruby, node, go, openjdk, openjdk_devel, rust, php, busybox, 389ds, metadata, minimal, multistage, repository, doc, lint, get_urls, pcp, distribution, postgres, git, helm, nginx, kernel_module, mariadb isolated_build = True skip_missing_interpreters = True @@ -22,6 +22,7 @@ deps = # Require a recent version of psycopg2 to avoid poo#128900 # 2.9.6 was the most up-to-date when adding this dependency psycopg2 >= 2.9.6 + pymysql allowlist_externals = docker podman