From c5cda73f22cb2dc0d33722a7c5ffec6195e6d5a8 Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Tue, 6 Jan 2026 15:25:45 +0100 Subject: [PATCH 1/4] Fix OpenShift 4 templates to using VARS named tuple variable Signed-off-by: Petr "Stone" Hracek --- test/constants.py | 5 -- test/test_ocp_psql_imagestream.py | 34 +++----------- test/test_ocp_psql_imagestream_template.py | 31 +++--------- test/test_ocp_psql_latest_imagestreams.py | 19 ++------ test/test_ocp_psql_template.py | 47 +++++++------------ .../test_ocp_shared_helm_psql_imagestreams.py | 31 ++++++------ test/test_ocp_shared_helm_psql_template.py | 40 +++++----------- 7 files changed, 58 insertions(+), 149 deletions(-) delete mode 100644 test/constants.py diff --git a/test/constants.py b/test/constants.py deleted file mode 100644 index 26eb71ae..00000000 --- a/test/constants.py +++ /dev/null @@ -1,5 +0,0 @@ -TAGS = { - "rhel8": "-el8", - "rhel9": "-el9", - "rhel10": "-el10", -} diff --git a/test/test_ocp_psql_imagestream.py b/test/test_ocp_psql_imagestream.py index 1252f405..bda37267 100644 --- a/test/test_ocp_psql_imagestream.py +++ b/test/test_ocp_psql_imagestream.py @@ -1,49 +1,29 @@ -import os -import sys - import pytest from container_ci_suite.openshift import OpenShiftAPI -from container_ci_suite.utils import check_variables - -from constants import TAGS - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) - -VERSION = os.getenv("VERSION") -IMAGE_NAME = os.getenv("IMAGE_NAME") -OS = os.getenv("TARGET") - -TAG = TAGS.get(OS) +from conftest import VARS class TestPostgreSQLImagestreamTemplate: - def setup_method(self): - self.oc_api = OpenShiftAPI(pod_name_prefix="postgresql", version=VERSION, shared_cluster=True) + self.oc_api = OpenShiftAPI( + pod_name_prefix="postgresql", version=VARS.VERSION, shared_cluster=True + ) def teardown_method(self): self.oc_api.delete_project() @pytest.mark.parametrize( "template", - [ - "postgresql-ephemeral-template.json", - "postgresql-persistent-template.json" - ] + ["postgresql-ephemeral-template.json", "postgresql-persistent-template.json"], ) def test_psql_imagestream_template(self, template): - os_name = ''.join(i for i in OS if not i.isdigit()) - print(os.getcwd()) + os_name = "".join(i for i in VARS.OS if not i.isdigit()) assert self.oc_api.deploy_image_stream_template( imagestream_file=f"imagestreams/postgresql-{os_name}.json", template_file=f"examples/{template}", app_name=self.oc_api.pod_name_prefix, - openshift_args=[ - f"POSTGRESQL_VERSION={VERSION}{TAG}" - ] + openshift_args=[f"POSTGRESQL_VERSION={VARS.VERSION}{VARS.TAG}"], ) assert self.oc_api.is_pod_running(pod_name_prefix=self.oc_api.pod_name_prefix) diff --git a/test/test_ocp_psql_imagestream_template.py b/test/test_ocp_psql_imagestream_template.py index b45d1e00..988278b9 100644 --- a/test/test_ocp_psql_imagestream_template.py +++ b/test/test_ocp_psql_imagestream_template.py @@ -1,45 +1,28 @@ -import os -import sys - import pytest from container_ci_suite.openshift import OpenShiftAPI -from container_ci_suite.utils import check_variables - -from constants import TAGS - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) - -VERSION = os.getenv("VERSION") -IMAGE_NAME = os.getenv("IMAGE_NAME") -OS = os.getenv("TARGET") - -TAG = TAGS.get(OS) +from conftest import VARS class TestPostgreSQLImagestreamTemplate: - def setup_method(self): - self.oc_api = OpenShiftAPI(pod_name_prefix="postgresql", version=VERSION, shared_cluster=True) + self.oc_api = OpenShiftAPI( + pod_name_prefix="postgresql", version=VARS.VERSION, shared_cluster=True + ) def teardown_method(self): self.oc_api.delete_project() @pytest.mark.parametrize( "template", - [ - "postgresql-ephemeral-template.json", - "postgresql-persistent-template.json" - ] + ["postgresql-ephemeral-template.json", "postgresql-persistent-template.json"], ) def test_psql_imagestream_template(self, template): - os_name = ''.join(i for i in OS if not i.isdigit()) + os_name = "".join(i for i in VARS.OS if not i.isdigit()) assert self.oc_api.deploy_image_stream_template( imagestream_file=f"imagestreams/postgresql-{os_name}.json", template_file=f"examples/{template}", - app_name=self.oc_api.pod_name_prefix + app_name=self.oc_api.pod_name_prefix, ) assert self.oc_api.is_pod_running(pod_name_prefix=self.oc_api.pod_name_prefix) diff --git a/test/test_ocp_psql_latest_imagestreams.py b/test/test_ocp_psql_latest_imagestreams.py index f01d442e..b357060f 100644 --- a/test/test_ocp_psql_latest_imagestreams.py +++ b/test/test_ocp_psql_latest_imagestreams.py @@ -1,26 +1,13 @@ -import os -import sys - -import pytest - -from pathlib import Path - from container_ci_suite.imagestreams import ImageStreamChecker -from container_ci_suite.utils import check_variables -TEST_DIR = Path(os.path.abspath(os.path.dirname(__file__))) - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) +from conftest import VARS class TestLatestImagestreams: - def setup_method(self): - self.isc = ImageStreamChecker(working_dir=TEST_DIR.parent) + self.isc = ImageStreamChecker(working_dir=VARS.TEST_DIR.parent) def test_latest_imagestream(self): self.latest_version = self.isc.get_latest_version() - assert self.latest_version != "" + assert self.latest_version self.isc.check_imagestreams(self.latest_version) diff --git a/test/test_ocp_psql_template.py b/test/test_ocp_psql_template.py index dc18cf76..5bcf73c7 100644 --- a/test/test_ocp_psql_template.py +++ b/test/test_ocp_psql_template.py @@ -1,59 +1,44 @@ -import os -import sys - import pytest from container_ci_suite.openshift import OpenShiftAPI -from container_ci_suite.utils import check_variables - -from constants import TAGS - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) - -VERSION = os.getenv("VERSION") -IMAGE_NAME = os.getenv("IMAGE_NAME") -OS = os.getenv("TARGET") - -TAG = TAGS.get(OS) +from conftest import VARS class TestPostgreSQLDeployTemplate: - def setup_method(self): - self.oc_api = OpenShiftAPI(pod_name_prefix="postgresql-testing", version=VERSION, shared_cluster=True) + self.oc_api = OpenShiftAPI( + pod_name_prefix="postgresql-testing", + version=VARS.VERSION, + shared_cluster=True, + ) def teardown_method(self): self.oc_api.delete_project() @pytest.mark.parametrize( "template", - [ - "postgresql-ephemeral-template.json", - "postgresql-persistent-template.json" - ] + ["postgresql-ephemeral-template.json", "postgresql-persistent-template.json"], ) def test_psql_template_inside_cluster(self, template): - short_version = VERSION.replace(".", "") + short_version = VARS.VERSION.replace(".", "") assert self.oc_api.deploy_template_with_image( - image_name=IMAGE_NAME, + image_name=VARS.IMAGE_NAME, template=f"examples/{template}", name_in_template="postgresql", openshift_args=[ - f"POSTGRESQL_VERSION={VERSION}", + f"POSTGRESQL_VERSION={VARS.VERSION}", f"DATABASE_SERVICE_NAME={self.oc_api.pod_name_prefix}", - f"POSTGRESQL_USER=testu", - f"POSTGRESQL_PASSWORD=testp", - f"POSTGRESQL_DATABASE=testdb" - ] + "POSTGRESQL_USER=testu", + "POSTGRESQL_PASSWORD=testp", + "POSTGRESQL_DATABASE=testdb", + ], ) assert self.oc_api.is_pod_running(pod_name_prefix=self.oc_api.pod_name_prefix) assert self.oc_api.check_command_internal( - image_name=f"registry.redhat.io/{OS}/postgresql-{short_version}", + image_name=f"registry.redhat.io/{VARS.OS}/postgresql-{short_version}", service_name=self.oc_api.pod_name_prefix, cmd="PGPASSWORD=testp pg_isready -t 15 -h -U testu -d testdb", - expected_output="accepting connections" + expected_output="accepting connections", ) diff --git a/test/test_ocp_shared_helm_psql_imagestreams.py b/test/test_ocp_shared_helm_psql_imagestreams.py index 19d108f4..1ad47c56 100644 --- a/test/test_ocp_shared_helm_psql_imagestreams.py +++ b/test/test_ocp_shared_helm_psql_imagestreams.py @@ -1,29 +1,23 @@ -import os -import sys - import pytest -from pathlib import Path - from container_ci_suite.helm import HelmChartsAPI -from container_ci_suite.utils import check_variables - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) -test_dir = Path(os.path.abspath(os.path.dirname(__file__))) +from conftest import VARS class TestHelmRHELPostgresqlImageStreams: - def setup_method(self): package_name = "redhat-postgresql-imagestreams" - path = test_dir - self.hc_api = HelmChartsAPI(path=path, package_name=package_name, tarball_dir=test_dir, shared_cluster=True) + self.hc_api = HelmChartsAPI( + path=VARS.TEST_DIR, + package_name=package_name, + tarball_dir=VARS.TEST_DIR, + shared_cluster=True, + ) self.hc_api.clone_helm_chart_repo( - repo_url="https://github.com/sclorg/helm-charts", repo_name="helm-charts", - subdir="charts/redhat" + repo_url="https://github.com/sclorg/helm-charts", + repo_name="helm-charts", + subdir="charts/redhat", ) def teardown_method(self): @@ -45,4 +39,7 @@ def teardown_method(self): def test_package_imagestream(self, version, registry, expected): assert self.hc_api.helm_package() assert self.hc_api.helm_installation() - assert self.hc_api.check_imagestreams(version=version, registry=registry) == expected + assert ( + self.hc_api.check_imagestreams(version=version, registry=registry) + == expected + ) diff --git a/test/test_ocp_shared_helm_psql_template.py b/test/test_ocp_shared_helm_psql_template.py index 1e86cacd..aeed2d1a 100644 --- a/test/test_ocp_shared_helm_psql_template.py +++ b/test/test_ocp_shared_helm_psql_template.py @@ -1,38 +1,18 @@ -import os -import sys - -import pytest - -from pathlib import Path - from container_ci_suite.helm import HelmChartsAPI -from container_ci_suite.utils import check_variables - -from constants import TAGS - -if not check_variables(): - print("At least one variable from IMAGE_NAME, OS, VERSION is missing.") - sys.exit(1) - -test_dir = Path(os.path.abspath(os.path.dirname(__file__))) - -VERSION = os.getenv("VERSION") -IMAGE_NAME = os.getenv("IMAGE_NAME") -OS = os.getenv("TARGET") - -TAG = TAGS.get(OS) +from conftest import VARS class TestHelmPostgresqlPersistent: - def setup_method(self): package_name = "redhat-postgresql-persistent" - path = test_dir - self.hc_api = HelmChartsAPI(path=path, package_name=package_name, tarball_dir=test_dir) + self.hc_api = HelmChartsAPI( + path=VARS.TEST_DIR, package_name=package_name, tarball_dir=VARS.TEST_DIR + ) self.hc_api.clone_helm_chart_repo( - repo_url="https://github.com/sclorg/helm-charts", repo_name="helm-charts", - subdir="charts/redhat" + repo_url="https://github.com/sclorg/helm-charts", + repo_name="helm-charts", + subdir="charts/redhat", ) def teardown_method(self): @@ -46,9 +26,11 @@ def test_package_persistent(self): assert self.hc_api.helm_package() assert self.hc_api.helm_installation( values={ - ".image.tag": f"{VERSION}{TAG}", + ".image.tag": f"{VARS.VERSION}{VARS.TAG}", ".namespace": self.hc_api.namespace, } ) - assert self.hc_api.is_pod_running(pod_name_prefix="redhat-postgresql-persistent") + assert self.hc_api.is_pod_running( + pod_name_prefix="redhat-postgresql-persistent" + ) assert self.hc_api.test_helm_chart(expected_str=["accepting connection"]) From 9c46f50f970e7e21cc501a77c4e98be0ed4d248c Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Tue, 6 Jan 2026 15:26:23 +0100 Subject: [PATCH 2/4] Add PyTest container test suite migrated from run_tests script The migration matrix is following: run_container_creation_tests -> test_container_configuration.py run_general_tests -> test_container_general.py run_change_password_test -> test_container_password.py run_replication_test -> test_container_replication.py run_s2i_test -> test_container_basics.py run_test_cfg_hook -> test_container_configuration.py run_s2i_bake_data_test -> test_container_ssl.py run_s2i_enable_ssl_test -> test_container_ssl.py run_pgaudit_test -> test_container_extensions.py run_pgvector_test -> test_container_extensions.py run_env_extension_load_test -> test_container_extensions.py run_logging_test -> test_container_extensions.py The following tests are NOT migrated yet. run_migration_test and run_upgrade_tests. Signed-off-by: Petr "Stone" Hracek --- test/conftest.py | 108 +++++++++++ test/run-pytest | 17 ++ test/test_container_basics.py | 105 +++++++++++ test/test_container_configuration.py | 259 +++++++++++++++++++++++++++ test/test_container_extensions.py | 175 ++++++++++++++++++ test/test_container_general.py | 215 ++++++++++++++++++++++ test/test_container_logging.py | 85 +++++++++ test/test_container_password.py | 189 +++++++++++++++++++ test/test_container_replication.py | 104 +++++++++++ test/test_container_ssl.py | 136 ++++++++++++++ 10 files changed, 1393 insertions(+) create mode 100644 test/conftest.py create mode 100755 test/run-pytest create mode 100644 test/test_container_basics.py create mode 100644 test/test_container_configuration.py create mode 100644 test/test_container_extensions.py create mode 100644 test/test_container_general.py create mode 100644 test/test_container_logging.py create mode 100644 test/test_container_password.py create mode 100644 test/test_container_replication.py create mode 100644 test/test_container_ssl.py diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 00000000..d570cbf1 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,108 @@ +import os +import sys +import tempfile + +from pathlib import Path +from collections import namedtuple + +from container_ci_suite.utils import check_variables +from container_ci_suite.utils import ContainerTestLibUtils + +if not check_variables(): + sys.exit(1) + +TAGS = { + "rhel8": "-el8", + "rhel9": "-el9", + "rhel10": "-el10", +} +TEST_DIR = Path(__file__).parent.absolute() +Vars = namedtuple( + "Vars", + [ + "OS", + "VERSION", + "IMAGE_NAME", + "TEST_DIR", + "TAG", + "TEST_APP", + "VERY_LONG_IDENTIFIER", + ], +) +VERSION = os.getenv("VERSION") +OS = os.getenv("TARGET").lower() +TEST_APP = TEST_DIR / "test-app" +VERY_LONG_IDENTIFIER = ( + "very_long_identifier_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +) +VARS = Vars( + OS=OS, + VERSION=VERSION, + IMAGE_NAME=os.getenv("IMAGE_NAME"), + TEST_DIR=Path(__file__).parent.absolute(), + TAG=TAGS.get(OS), + TEST_APP=TEST_APP, + VERY_LONG_IDENTIFIER=VERY_LONG_IDENTIFIER, +) + + +def get_previous_major_version(): + version_dict = { + "13": "12", + "15": "13", + "16": "15", + } + return version_dict.get(VARS.VERSION) + + +def get_upgrade_path(): + upgrade_path = { + "rhel8": "none 12 13 15 16 none", + "rhel9": "none 13 15 16 none", + "rhel10": "none 13 15 16 none", + "fedora": "none 12 13 14 15 16 none", + } + for version in upgrade_path.keys(): + if version == VARS.VERSION: + break + prev = version + if prev == "none": + return None + return prev + + +def get_image_id(version): + ns = { + "rhel8": f"registry.redhat.io/rhel8/postgresql-{version}", + "rhel9": f"registry.redhat.io/rhel9/postgresql-{version}", + "rhel10": f"registry.redhat.io/rhel10/postgresql-{version}", + "c9s": f"quay.io/sclorg/postgresql-{version}-c9s", + "c10s": f"quay.io/sclorg/postgresql-{version}-c10s", + } + return ns[VARS.OS] + + +def create_postgresql_volume_dir(): + """ + Create a PostgreSQL volume directory and set the permissions to 26:-wx. + """ + volume_dir = tempfile.mkdtemp(prefix="/tmp/psql-volume-dir") + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -m u:26:-wx {volume_dir}", + ] + ) + return volume_dir + + +def create_postgresql_temp_file(): + """ + Create a PostgreSQL temporary file and set the permissions to 26:rw-. + """ + temp_file = tempfile.mktemp(prefix="/tmp/psql-temp-file") + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -m u:26:rw- {temp_file}", + ] + ) + return temp_file diff --git a/test/run-pytest b/test/run-pytest new file mode 100755 index 00000000..202bd144 --- /dev/null +++ b/test/run-pytest @@ -0,0 +1,17 @@ +#!/bin/bash +# +# IMAGE_NAME specifies a name of the candidate image used for testing. +# The image has to be available before this script is executed. +# VERSION specifies the major version of the PostgreSQL in format of X.Y +# OS specifies RHEL version (e.g. OS=rhel10) +# + +THISDIR=$(dirname ${BASH_SOURCE[0]}) + +git show -s + +PYTHON_VERSION="3.12" +if [[ ! -f "/usr/bin/python$PYTHON_VERSION" ]]; then + PYTHON_VERSION="3.13" +fi +cd "${THISDIR}" && "python${PYTHON_VERSION}" -m pytest -s -rA --showlocals -vv test_container_*.py diff --git a/test/test_container_basics.py b/test/test_container_basics.py new file mode 100644 index 00000000..20a376da --- /dev/null +++ b/test/test_container_basics.py @@ -0,0 +1,105 @@ +from pathlib import Path + +from container_ci_suite.container_lib import ContainerTestLib + +from conftest import VARS, create_postgresql_temp_file + + +def build_s2i_app(app_path: Path) -> ContainerTestLib: + container_lib = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") + app_name = app_path.name + s2i_app = container_lib.build_as_df( + app_path=app_path, + s2i_args="--pull-policy=never", + src_image=VARS.IMAGE_NAME, + dst_image=f"{VARS.IMAGE_NAME}-{app_name}", + ) + return s2i_app + + +class TestPostgreSQLBasicsContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + self.app_image = build_s2i_app(app_path=VARS.TEST_DIR / "test-app") + self.app_image.db_lib.db_type = "postgresql" + + def teardown_method(self): + self.app_image.cleanup() + + def test_s2i_usage(self): + """ + Test container creation fails with invalid combinations of arguments. + """ + cid_config_build = "s2i_config_build" + psql_password = "password" + psql_database = "db" + psql_user = "user" + psql_admin_password = psql_password + psql_backup_user = "backuser" + psql_backup_password = "pass" + self.app_image.assert_container_creation_fails( + cid_file_name=cid_config_build, + command="", + container_args=[ + "-e POSTGRESQL_PASSWORD=pass", + f"-e POSTGRESQL_DATABASE={psql_database}", + ], + ) + assert self.app_image.create_container( + cid_file_name=cid_config_build, + docker_args=[ + f"-e POSTGRESQL_USER={psql_user}", + f"-e POSTGRESQL_PASSWORD={psql_password}", + f"-e POSTGRESQL_DATABASE={psql_database}", + f"-e POSTGRESQL_BACKUP_USER={psql_backup_user}", + f"-e POSTGRESQL_BACKUP_PASSWORD={psql_backup_password}", + f"-e POSTGRESQL_ADMIN_PASSWORD={psql_admin_password}", + ], + ) + cip = self.app_image.get_cip(cid_file_name=cid_config_build) + assert cip + assert self.app_image.test_db_connection( + container_ip=cip, username=psql_user, password=psql_password + ) + assert self.app_image.test_db_connection( + container_ip=cip, + username=psql_backup_user, + password=psql_backup_password, + database="backup", + ) + tmp_file = create_postgresql_temp_file() + backup_user_script = ( + VARS.TEST_DIR / "test-app" / "postgresql-init" / "backup_user.sh" + ) + with open(backup_user_script, "r") as f: + backup_user_script_content = f.read() + with open(tmp_file, "w") as f: + f.write(backup_user_script_content) + cid_s2i_test_mount = "s2i_test_mount" + mount_point = "/opt/app-root/src/postgresql-init/add_backup_user.sh" + assert self.app_image.create_container( + cid_file_name=cid_s2i_test_mount, + docker_args=[ + f"-e POSTGRESQL_USER={psql_user}", + f"-e POSTGRESQL_PASSWORD={psql_password}", + f"-e POSTGRESQL_DATABASE={psql_database}", + f"-e POSTGRESQL_BACKUP_USER={psql_backup_user}", + f"-e POSTGRESQL_BACKUP_PASSWORD={psql_backup_password}", + f"-e POSTGRESQL_ADMIN_PASSWORD={psql_admin_password}", + f"-v {tmp_file}:{mount_point}:z,ro", + ], + ) + cip = self.app_image.get_cip(cid_file_name=cid_s2i_test_mount) + assert cip + assert self.app_image.test_db_connection( + container_ip=cip, username=psql_user, password=psql_password + ) + assert self.app_image.test_db_connection( + container_ip=cip, + username=psql_backup_user, + password=psql_backup_password, + database="backup", + ) diff --git a/test/test_container_configuration.py b/test/test_container_configuration.py new file mode 100644 index 00000000..3e012057 --- /dev/null +++ b/test/test_container_configuration.py @@ -0,0 +1,259 @@ +import pytest + +from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.engines.database import DatabaseWrapper + +from conftest import VARS, create_postgresql_volume_dir + + +class TestPostgreSQLConfigurationContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.db = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") + self.db_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.db.cleanup() + + def test_container_creation_fails(self): + """ + Test container creation fails with no arguments. + """ + cid_config_test = "container_creation_fails" + assert self.db.assert_container_creation_fails( + cid_file_name=cid_config_test, container_args=[], command="" + ) + + @pytest.mark.parametrize( + "psql_user, psql_password, psql_database", + [ + ( + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=pass", + "", + ), + ( + "-e POSTGRESQL_USER=user", + "", + "-e POSTGRESQL_DATABASE=db", + ), + ( + "", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=db", + ), + ], + ) + def test_try_image_invalid_combinations( + self, psql_user, psql_password, psql_database + ): + """ + Test container creation fails with invalid combinations of arguments. + """ + assert self.db.assert_container_creation_fails( + cid_file_name="try_image_invalid_combinations", + container_args=[psql_user, psql_password, psql_database], + command="", + ) + assert self.db.assert_container_creation_fails( + cid_file_name="try_image_invalid_combinations", + container_args=[ + psql_user, + psql_password, + psql_database, + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + command="", + ) + + @pytest.mark.parametrize( + "psql_user, psql_password, psql_database, psql_admin_password", + [ + [ + "-e POSTGRESQL_USER=", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=db", + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + [ + f"-e POSTGRESQL_USER={VARS.VERY_LONG_IDENTIFIER}", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=db", + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + [ + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=pass", + f"-e POSTGRESQL_DATABASE={VARS.VERY_LONG_IDENTIFIER}", + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + ], + ) + def test_invalid_configuration_tests( + self, + psql_user, + psql_password, + psql_database, + psql_admin_password, + ): + """ + Test invalid configuration combinations for PostgreSQL container. + """ + assert self.db.assert_container_creation_fails( + cid_file_name="invalid_configuration_tests", + container_args=[ + psql_user, + psql_password, + psql_database, + psql_admin_password, + ], + command="", + ) + + @pytest.mark.parametrize( + "psql_user, psql_password, psql_database, psql_admin_password", + [ + [ + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=", + "-e POSTGRESQL_DATABASE=db", + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + [ + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=9invalid", + "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + ], + [ + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=db", + "-e POSTGRESQL_ADMIN_PASSWORD=", + ], + [ + "-e POSTGRESQL_USER=user", + "-e POSTGRESQL_PASSWORD=pass", + "-e POSTGRESQL_DATABASE=db", + "-e POSTGRESQL_ADMIN_PASSWORD=", + ], + [ + "-e POSTGRESQL_USER=", + "-e POSTGRESQL_PASSWORD=", + "-e POSTGRESQL_DATABASE=", + '-e POSTGRESQL_ADMIN_PASSWORD="The @password"', + ], + [ + '-e POSTGRESQL_USER="the user"', + '-e POSTGRESQL_PASSWORD="the pass"', + '-e POSTGRESQL_DATABASE="the db"', + "-e POSTGRESQL_ADMIN_PASSWORD=", + ], + ], + ) + def test_correct_configuration_tests( + self, + psql_user, + psql_password, + psql_database, + psql_admin_password, + ): + """ + Test correct configuration combinations for PostgreSQL container. + """ + assert self.db.assert_container_creation_succeeds( + container_args=[ + psql_user, + psql_password, + psql_database, + psql_admin_password, + ], + command="", + ) + + def test_configuration_hook(self): + """ + Test container creation fails with no arguments. + """ + cid_file_name = "test_pg_hook" + volume_dir = create_postgresql_volume_dir() + docker_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=password", + "-e POSTGRESQL_SHARED_BUFFERS=32MB", + f"-v {volume_dir}:/opt/app-root/src:Z", + ] + assert self.db.create_container( + cid_file_name=cid_file_name, + docker_args=docker_args, + command="", + ) + cid = self.db.get_cid(cid_file_name=cid_file_name) + assert cid + cip = self.db.get_cip(cid_file_name=cid_file_name) + assert cip + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd='psql -tA -c "SHOW shared_buffers;"', + ) + assert "32MB" in output, f"Shared buffers should be 32MB, but is {output}" + # Check that POSTGRESQL_SHARED_BUFFERS has effect. + docker_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=password", + "-e POSTGRESQL_SHARED_BUFFERS=113MB", + ] + cid_file_name2 = "test_pg_hook_2" + assert self.db.create_container( + cid_file_name=cid_file_name2, + docker_args=docker_args, + command="", + ) + cid = self.db.get_cid(cid_file_name=cid_file_name2) + assert cid + cip = self.db.get_cip(cid_file_name=cid_file_name2) + assert cip + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd='psql -tA -c "SHOW shared_buffers;"', + ) + assert "113MB" in output, f"Shared buffers should be 113MB, but is {output}" + # Check that volume has priority over POSTGRESQL_SHARED_BUFFERS. + cid_file_name3 = "test_pg_hook_3" + docker_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=password", + "-e POSTGRESQL_SHARED_BUFFERS=113MB", + f"-v {volume_dir}:/opt/app-root/src:Z", + ] + assert self.db.create_container( + cid_file_name=cid_file_name3, + docker_args=docker_args, + command="", + ) + cid = self.db.get_cid(cid_file_name=cid_file_name3) + assert cid + cip = self.db.get_cip(cid_file_name=cid_file_name3) + assert cip + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd='psql -tA -c "SHOW shared_buffers;"', + ) + + assert "113MB" in output, f"Shared buffers should be 113MB, but is {output}" diff --git a/test/test_container_extensions.py b/test/test_container_extensions.py new file mode 100644 index 00000000..8c9d0c8f --- /dev/null +++ b/test/test_container_extensions.py @@ -0,0 +1,175 @@ +import re +import os +import tempfile + +from time import sleep +from pathlib import Path + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.container_lib import ContainerTestLibUtils +from container_ci_suite.engines.database import DatabaseWrapper +from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper +from container_ci_suite.utils import get_file_content + +import pytest + +from conftest import VARS, create_postgresql_volume_dir + + +class TestPostgreSQLPluginContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.db = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") + self.db_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.db.cleanup() + + @pytest.mark.parametrize( + "env_load", + [ + (""), + ("-e POSTGRESQL_EXTENSIONS=pgaudit -e POSTGRESQL_LIBRARIES=pgaudit"), + ], + ) + def test_pgaudit_extension_installation(self, env_load): + """ + Test pogaudit installation. + """ + if VARS.VERSION in ["9.6", "10", "11"]: + pytest.skip("pgaudit not expected, test skipped.") + cid_file_name = "test_pg_pgaudit" + config_dir = tempfile.mkdtemp(prefix="/tmp/psql-pgaudit-volume") + sql_cmd1 = "SET pgaudit.log = 'read, ddl';\nCREATE DATABASE pgaudittest;" + sql_cmd2 = "SET pgaudit.log = 'read, ddl';\nCREATE TABLE account \ + (id int, name text, password text, description text);" + sql_cmd3 = "INSERT INTO account (id, name, password, description) \ + VALUES (1, 'user1', 'HASH1', 'blah, blah');\nSELECT * FROM account;" + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -R -m u:26:rwx {config_dir}", + f"cp -r {VARS.TEST_DIR}/examples/pgaudit/* {config_dir}/", + f"setfacl -R -m u:26:rwx {config_dir}", + f"echo '{sql_cmd1}' > {config_dir}/enable-extension.sql", + f"echo '{sql_cmd2}' > {config_dir}/insert-data.sql", + f"echo '{sql_cmd3}' >> {config_dir}/insert-data.sql", + f"cat {config_dir}/enable-extension.sql", + f"cat {config_dir}/insert-data.sql", + ] + ) + volume_dir = create_postgresql_volume_dir() + docker_args = [ + env_load, + "-e POSTGRESQL_ADMIN_PASSWORD=password", + f"-v {config_dir}:/opt/app-root/src:Z", + f"-v {volume_dir}:/var/lib/pgsql/data:Z", + ] + + assert self.db.create_container( + cid_file_name=cid_file_name, + docker_args=docker_args, + command="", + ) + cip = self.db.get_cip(cid_file_name=cid_file_name) + assert cip + cid = self.db.get_cid(cid_file_name=cid_file_name) + assert cid + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd='psql -tA -c "SHOW shared_preload_libraries;"', + ) + assert "pgaudit" in output, ( + f"pgaudit should be in the shared_preload_libraries, but is {output}" + ) + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.call_podman_command( + cmd=f'exec {cid} bash -c "psql < /opt/app-root/src/enable-extension.sql"', + ) + output = PodmanCLIWrapper.call_podman_command( + cmd=f'exec {cid} bash -c "psql < /opt/app-root/src/insert-data.sql"', + ) + sleep(1) + log_files_to_check = [] + for f in os.listdir(Path(volume_dir) / "userdata" / "log"): + if f.startswith("postgresql-"): + log_files_to_check.append(Path(volume_dir) / "userdata" / "log" / f) + for f in log_files_to_check: + output = get_file_content( + filename=f, + ) + words_to_check = [ + "AUDIT: SESSION,.*,.*,DDL,CREATE DATABASE,,,CREATE DATABASE pgaudittest", + "AUDIT: SESSION,.*,.*,READ,SELECT,,,SELECT", + ] + for word in words_to_check: + assert re.search(word, output), ( + f"{word} should be in the output, but is {output}" + ) + + def test_pgvector(self): + """ + Test pgvector installation. + """ + if VARS.VERSION in ["11", "12", "13", "15"]: + pytest.skip("pgvector not expected on this version, test skipped.") + if VARS.OS == "rhel8": + pytest.skip("pgvector not expected on this OS, test skipped.") + cid_file_name = "test_pg_pgvector" + config_dir = tempfile.mkdtemp(prefix="/tmp/psql-pgvector-volume") + sql_cmd = "CREATE EXTENSION vector;\nCREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));" + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -R -m u:26:rwx {config_dir}", + f"cp -r {VARS.TEST_DIR}/examples/pgvector/* {config_dir}/", + f"setfacl -R -m u:26:rwx {config_dir}", + f"echo '{sql_cmd}' > {config_dir}/enable-vector.sql", + ] + ) + volume_dir = create_postgresql_volume_dir() + docker_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=password", + f"-v {config_dir}:/opt/app-root/src:Z", + f"-v {volume_dir}:/var/lib/pgsql/data:Z", + ] + + assert self.db.create_container( + cid_file_name=cid_file_name, + docker_args=docker_args, + command="", + ) + cip = self.db.get_cip(cid_file_name=cid_file_name) + assert cip + cid = self.db.get_cid(cid_file_name=cid_file_name) + assert cid + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd='psql -tA -c "SHOW shared_preload_libraries;"', + ) + assert "vector" in output, ( + f"pgaudit should be in the shared_preload_libraries, but is {output}" + ) + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + output = PodmanCLIWrapper.call_podman_command( + cmd=f'exec {cid} bash -c "psql < /opt/app-root/src/enable-vector.sql"', + ) + sleep(1) + assert output diff --git a/test/test_container_general.py b/test/test_container_general.py new file mode 100644 index 00000000..2d481382 --- /dev/null +++ b/test/test_container_general.py @@ -0,0 +1,215 @@ +import re +import pytest + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper +from container_ci_suite.container_lib import DatabaseWrapper + +from conftest import VARS + + +class TestPostgreSQLGeneralContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.db_image = ContainerTestLib( + image_name=VARS.IMAGE_NAME, db_type="postgresql" + ) + self.db_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.db_image.cleanup() + + @pytest.mark.parametrize( + "docker_args, psql_user, psql_password, psql_database, root_password, test_name", + [ + ("", "user", "pass", "", "", "no_admin"), + ("", "user1", "pass1", "", "r00t", "admin"), + # ("", "", "", "postgres", "r00t", "only_admin"), + ("-u 12345", "user2", "pass", "", "", "no_admin_altuid"), + ("-u 12345", "user3", "pass1", "", "r00t", "admin_altuid"), + # ("-u 12345", "", "", "postgres", "r00t", "only_admin_altuid"), + ], + ) + def test_run( + self, + docker_args, + psql_user, + psql_password, + psql_database, + root_password, + test_name, + ): + """ + Test PostgreSQL container general usage. + """ + POSTGRESQL_MAX_CONNECTIONS = 100 + POSTGRESQL_MAX_PREPARED_TRANSACTIONS = 0 + POSTGRESQL_SHARED_BUFFERS = "32MB" + if test_name == "no_admin": + POSTGRESQL_MAX_CONNECTIONS = 42 + POSTGRESQL_MAX_PREPARED_TRANSACTIONS = 42 + POSTGRESQL_SHARED_BUFFERS = "64MB" + expected_success = False + expected_admin_success = False + if psql_user != "": + psql_user_arg = f"-e POSTGRESQL_USER={psql_user}" + expected_success = True + else: + psql_user_arg = "" + if psql_password: # empty password is allowed + psql_pwd_arg = f"-e POSTGRESQL_PASSWORD={psql_password}" + else: + psql_pwd_arg = "" + if psql_database: + db_name = psql_database + else: + db_name = "db" + if root_password == "r00t": + admin_root_password_arg = f"-e POSTGRESQL_ADMIN_PASSWORD={root_password}" + expected_admin_success = True + else: + admin_root_password_arg = "" + docker_all_args = [ + psql_user_arg, + psql_pwd_arg, + f"-e POSTGRESQL_DATABASE={db_name}", + admin_root_password_arg, + f"-e POSTGRESQL_MAX_CONNECTIONS={POSTGRESQL_MAX_CONNECTIONS}", + f"-e POSTGRESQL_MAX_PREPARED_TRANSACTIONS={POSTGRESQL_MAX_PREPARED_TRANSACTIONS}", + f"-e POSTGRESQL_SHARED_BUFFERS={POSTGRESQL_SHARED_BUFFERS}", + f"{docker_args}", + ] + cid_file_name = test_name + assert self.db_image.create_container( + cid_file_name=cid_file_name, docker_args=docker_all_args + ) + cip = self.db_image.get_cip(cid_file_name=cid_file_name) + assert cip + if root_password: + assert self.db_image.test_db_connection( + container_ip=cip, + username="postgres", + password=root_password, + database="postgres", + max_attempts=10, + ) + else: + assert self.db_image.test_db_connection( + container_ip=cip, + username=psql_user, + password=psql_password, + max_attempts=10, + ) + cid = self.db_image.get_cid(cid_file_name=cid_file_name) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd="psql --version", + ) + assert VARS.VERSION in output + self.db_image.db_lib.assert_login_access( + container_ip=cip, + username=psql_user, + password=psql_password, + expected_success=expected_success, + ) + self.db_image.db_lib.assert_login_access( + container_ip=cip, + username=psql_user, + password=f"{psql_password}_foo", + expected_success=False, + ) + self.db_image.db_lib.assert_login_access( + container_ip=cip, + username="postgres", + password=root_password, + expected_success=expected_admin_success, + ) + self.db_image.db_lib.assert_login_access( + container_ip=cip, + username="postgres", + password=f"{root_password}_foo", + expected_success=False, + ) + assert self.db_image.db_lib.assert_local_access(container_id=cid) + output = PodmanCLIWrapper.podman_exec_shell_command( + cid_file_name=cid, + cmd="cat /var/lib/pgsql/openshift-custom-postgresql.conf", + ) + + words = [ + f"max_connections\\s*=\\s*{POSTGRESQL_MAX_CONNECTIONS}", + f"max_prepared_transactions\\s*=\\s*{POSTGRESQL_MAX_PREPARED_TRANSACTIONS}", + f"shared_buffers\\s*=\\s*{POSTGRESQL_SHARED_BUFFERS}", + ] + for word in words: + assert re.search(word, output), f"Word {word} not found in {output}" + # test_postgresql + if test_name == "admin": + psql_user = "postgres" + psql_password = root_password + psql_database = "postgres" + output = self.db_api.run_sql_command( + container_ip=cip, + username=psql_user, + password=psql_password, + container_id=VARS.IMAGE_NAME, + database=db_name, + sql_cmd="-At -c 'CREATE EXTENSION \"uuid-ossp\";'", + expected_output="CREATE EXTENSION", + ) + output = self.db_api.run_sql_command( + container_ip=cip, + username=psql_user, + password=psql_password, + container_id=VARS.IMAGE_NAME, + database=db_name, + sql_cmd='-At -c "CREATE TABLE tbl (a integer, b integer);"', + expected_output="CREATE TABLE", + ) + + output = self.db_api.run_sql_command( + container_ip=cip, + username=psql_user, + password=psql_password, + container_id=VARS.IMAGE_NAME, + database=db_name, + sql_cmd=[ + '-At -c "INSERT INTO tbl VALUES (1, 2);"', + '-At -c "INSERT INTO tbl VALUES (3, 4);"', + '-At -c "INSERT INTO tbl VALUES (5, 6);"', + ], + expected_output="INSERT 0 1", + ) + output = self.db_api.run_sql_command( + container_ip=cip, + username=psql_user, + password=psql_password, + container_id=VARS.IMAGE_NAME, + database=db_name, + sql_cmd='-At -c "SELECT * FROM tbl;"', + ) + words = [ + "1|2", + "3|4", + "5|6", + ] + for word in words: + assert re.search(word, output), f"Word {word} not found in {output}" + self.db_api.run_sql_command( + container_ip=cip, + username=psql_user, + password=psql_password, + container_id=VARS.IMAGE_NAME, + database=db_name, + sql_cmd='-At -c "DROP TABLE tbl;"', + expected_output="DROP TABLE", + ) diff --git a/test/test_container_logging.py b/test/test_container_logging.py new file mode 100644 index 00000000..853c70aa --- /dev/null +++ b/test/test_container_logging.py @@ -0,0 +1,85 @@ +import re + +from pathlib import Path + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.engines.database import DatabaseWrapper +from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper + +from conftest import VARS, create_postgresql_volume_dir + + +class TestPostgreSQLLoggingContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.db = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") + self.db_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.db.cleanup() + + def test_logging_destination(self): + """ + Test logging destination. + """ + cid_file_name = "test_pg_logging" + volume_dir = create_postgresql_volume_dir() + docker_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=password", + "-e POSTGRESQL_LOG_DESTINATION=/dev/stderr", + f"-v {volume_dir}:/var/lib/pgsql/data:Z", + ] + + assert self.db.create_container( + cid_file_name=cid_file_name, + docker_args=docker_args, + command="", + ) + cip = self.db.get_cip(cid_file_name=cid_file_name) + assert cip + cid = self.db.get_cid(cid_file_name=cid_file_name) + assert cid + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + + output = PodmanCLIWrapper.call_podman_command( + cmd=f"exec {cid} bash -c \"psql -tA -c 'SHOW log_destination;'\"", + ) + # TODO NEED TO FIX THIS + # assert "logging_collector log_directory log_filename" in output, ( + # f"logging_collector log_directory log_filename should be in the log_destination, but is {output}" + # ) + assert "stderr" in output, ( + f"stderr should be in the log_destination, but is {output}" + ) + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + + output = PodmanCLIWrapper.call_podman_command( + cmd=f"exec {cid} bash -c 'psql -U nonexistent'", + ignore_error=True, + ) + + assert self.db_api.wait_for_database( + container_id=cid, command="/usr/libexec/check-container" + ) + logs = PodmanCLIWrapper.podman_logs( + container_id=cid, + ) + assert re.search('FATAL:\\s*role "nonexistent" does not exist', logs), ( + "ERROR: the container log does not include expected error message" + ) + assert not (Path(volume_dir) / "userdata" / "log").exists(), ( + f"ERROR: the traditional log file {Path(volume_dir) / 'userdata' / 'log'} should not exist" + ) diff --git a/test/test_container_password.py b/test/test_container_password.py new file mode 100644 index 00000000..29dd319f --- /dev/null +++ b/test/test_container_password.py @@ -0,0 +1,189 @@ +import tempfile +import re + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.container_lib import ContainerTestLibUtils +from container_ci_suite.container_lib import DatabaseWrapper +from container_ci_suite.engines.podman_wrapper import PodmanCLIWrapper + +from conftest import VARS + + +class TestPostgreSQLPasswordChangeContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.pwd_change = ContainerTestLib(image_name=VARS.IMAGE_NAME) + self.pwd_change.set_new_db_type(db_type="postgresql") + self.dw_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.pwd_change.cleanup() + + def test_password_change(self): + """ + Test password change. + """ + cid_file_name1 = "test_password_change" + pwd_dir = tempfile.mkdtemp(prefix="/tmp/psql-pwd") + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -m u:26:-wx {pwd_dir}", + ] + ) + volume_options = f"-v {pwd_dir}:/var/lib/pgsql/data:Z" + database = "db" + username = "user" + password = "password" + admin_password = "adminPassword" + assert self.pwd_change.create_container( + cid_file_name=cid_file_name1, + docker_args=[ + f"-e POSTGRESQL_USER={username}", + f"-e POSTGRESQL_PASSWORD={password}", + f"-e POSTGRESQL_DATABASE={database}", + f"-e POSTGRESQL_ADMIN_PASSWORD={admin_password}", + volume_options, + ], + ) + cip1 = self.pwd_change.get_cip(cid_file_name=cid_file_name1) + assert cip1 + assert self.pwd_change.test_db_connection( + container_ip=cip1, + username=username, + password=password, + max_attempts=10, + ) + cid1 = self.pwd_change.get_cid(cid_file_name=cid_file_name1) + assert cid1 + self.pwd_change.db_lib.assert_login_access( + container_ip=cip1, + username=username, + password=password, + expected_success=True, + ) + self.pwd_change.db_lib.assert_login_access( + container_ip=cip1, + username="postgres", + password=admin_password, + expected_success=True, + ) + assert self.pwd_change.test_db_connection( + container_ip=cip1, username=username, password=password + ) + # test_postgresql + output = self.dw_api.run_sql_command( + container_ip=cip1, + username=username, + password=password, + container_id=VARS.IMAGE_NAME, + database=database, + sql_cmd='-At -c "CREATE TABLE tbl (a integer, b integer);"', + expected_output="CREATE TABLE", + ) + + output = self.dw_api.run_sql_command( + container_ip=cip1, + username=username, + password=password, + container_id=VARS.IMAGE_NAME, + database=database, + sql_cmd=[ + '-At -c "INSERT INTO tbl VALUES (1, 2);"', + '-At -c "INSERT INTO tbl VALUES (3, 4);"', + '-At -c "INSERT INTO tbl VALUES (5, 6);"', + ], + expected_output="INSERT 0 1", + ) + output = self.dw_api.run_sql_command( + container_ip=cip1, + username=username, + password=password, + container_id=VARS.IMAGE_NAME, + database=database, + sql_cmd='-At -c "SELECT * FROM tbl;"', + ) + words = [ + "1|2", + "3|4", + "5|6", + ] + for word in words: + assert re.search(word, output), f"Word {word} not found in {output}" + PodmanCLIWrapper.call_podman_command(cmd=f"kill {cid1}") + PodmanCLIWrapper.call_podman_command(cmd=f"rm -f {cid1}") + cid_file_name_new = "test_password_change_new_password" + new_password = f"NEW_{password}" + new_admin_password = f"NEW_{admin_password}" + assert self.pwd_change.create_container( + cid_file_name=cid_file_name_new, + docker_args=[ + f"-e POSTGRESQL_USER={username}", + f"-e POSTGRESQL_PASSWORD={new_password}", + f"-e POSTGRESQL_DATABASE={database}", + f"-e POSTGRESQL_ADMIN_PASSWORD={new_admin_password}", + volume_options, + ], + ) + cip_new = self.pwd_change.get_cip(cid_file_name=cid_file_name_new) + assert cip_new + assert self.pwd_change.test_db_connection( + container_ip=cip_new, + username=username, + password=new_password, + max_attempts=10, + ) + self.pwd_change.db_lib.assert_login_access( + container_ip=cip_new, + username=username, + password=new_password, + expected_success=True, + ) + self.pwd_change.db_lib.assert_login_access( + container_ip=cip_new, + username=username, + password=password, + expected_success=False, + ) + self.pwd_change.db_lib.assert_login_access( + container_ip=cip_new, + username="postgres", + password=new_admin_password, + expected_success=True, + ) + self.pwd_change.db_lib.assert_login_access( + container_ip=cip_new, + username="postgres", + password=admin_password, + expected_success=False, + ) + output = self.dw_api.run_sql_command( + container_ip=cip_new, + username=username, + password=password, + container_id=VARS.IMAGE_NAME, + ignore_error=True, + ) + output = self.dw_api.run_sql_command( + container_ip=cip_new, + username=username, + password=new_password, + container_id=VARS.IMAGE_NAME, + database=database, + sql_cmd='-At -c "SELECT * FROM tbl;"', + ) + words = [ + "1|2", + "3|4", + "5|6", + ] + for word in words: + assert re.search(word, output), f"Word {word} not found in {output}" diff --git a/test/test_container_replication.py b/test/test_container_replication.py new file mode 100644 index 00000000..4e2f7b87 --- /dev/null +++ b/test/test_container_replication.py @@ -0,0 +1,104 @@ +import re + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.engines.database import DatabaseWrapper + +from conftest import VARS + + +class TestPostgreSQLReplicationContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.replication_db = ContainerTestLib( + image_name=VARS.IMAGE_NAME, db_type="postgresql" + ) + self.db_wrapper_api = DatabaseWrapper( + image_name=VARS.IMAGE_NAME, db_type="postgresql" + ) + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.replication_db.cleanup() + + def test_replication(self): + """ + Test replication. + """ + database = "postgres" + master_user = "master" + master_password = "master" + master_hostname = "postgresql-master" + + cluster_args = [ + "-e POSTGRESQL_ADMIN_PASSWORD=pass", + f"-e POSTGRESQL_MASTER_USER={master_user}", + f"-e POSTGRESQL_MASTER_PASSWORD={master_password}", + ] + master_cid_name = "master-basic" + # Run the PostgreSQL master + assert self.replication_db.create_container( + cid_file_name=master_cid_name, + docker_args=cluster_args, + command="run-postgresql-master", + ) + # Run the PostgreSQL replica + master_cip = self.replication_db.get_cip(cid_file_name=master_cid_name) + assert master_cip + master_cid = self.replication_db.get_cid(cid_file_name=master_cid_name) + assert master_cid + cluster_args += [ + f"--add-host {master_hostname}:{master_cip}", + f"-e POSTGRESQL_MASTER_IP={master_hostname}", + ] + slave_cid_name = "slave-basic-1" + assert self.replication_db.create_container( + cid_file_name=slave_cid_name, + docker_args=cluster_args, + command="run-postgresql-slave", + ) + slave_cip = self.replication_db.get_cip(cid_file_name=slave_cid_name) + assert slave_cip + slave_cid = self.replication_db.get_cid(cid_file_name=slave_cid_name) + assert slave_cid + output = self.db_wrapper_api.run_sql_command( + container_ip=master_cip, + username=master_user, + password=master_password, + database=database, + sql_cmd="-c 'select client_addr from pg_stat_replication;'", + ignore_error=True, + expected_output=f"{slave_cip}", + ) + assert slave_cip in output, ( + f"Replica {slave_cip} not found in MASTER {master_cip}" + ) + # Test the replication + table_name = "t1" + value = 24 + output = self.db_wrapper_api.run_sql_command( + container_ip=master_cip, + username=master_user, + password=master_password, + database=database, + sql_cmd=f"-c 'CREATE TABLE {table_name} (a integer); INSERT INTO {table_name} VALUES ({value});'", + expected_output="INSERT 0 1", + ) + output = self.db_wrapper_api.run_sql_command( + container_ip=slave_cip, + username=master_user, + password=master_password, + database=database, + sql_cmd=f"-At -c 'select * from {table_name};'", + expected_output=f"{value}", + ) + assert re.search(f"{value}", output), ( + f"Value {value} not found in REPLICA {slave_cip} for table {table_name}" + ) diff --git a/test/test_container_ssl.py b/test/test_container_ssl.py new file mode 100644 index 00000000..2072019b --- /dev/null +++ b/test/test_container_ssl.py @@ -0,0 +1,136 @@ +import re + +from pathlib import Path + +from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.engines.database import DatabaseWrapper + +from conftest import VARS + + +def build_s2i_app(app_path: Path) -> ContainerTestLib: + container_lib = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") + app_name = app_path.name + s2i_app = container_lib.build_as_df( + app_path=app_path, + s2i_args="--pull-policy=never", + src_image=VARS.IMAGE_NAME, + dst_image=f"{VARS.IMAGE_NAME}-{app_name}", + ) + return s2i_app + + +class TestPostgreSQLS2ISSLContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.ssl_db = build_s2i_app(app_path=VARS.TEST_DIR / "examples" / "enable-ssl") + self.ssl_db.db_lib.db_type = "postgresql" + self.dw_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.ssl_db.cleanup() + + def test_ssl(self): + """ + Test SSL. + """ + cid_ssl_name = "enable-ssl-test" + admin_password = "password" + + assert self.ssl_db.create_container( + cid_file_name=cid_ssl_name, + docker_args=[ + f"-e POSTGRESQL_ADMIN_PASSWORD={admin_password}", + ], + ) + assert self.dw_api.wait_for_database( + container_id=self.ssl_db.get_cid(cid_file_name=cid_ssl_name), + command="/usr/libexec/check-container", + ) + ssl_cip = self.ssl_db.get_cip(cid_file_name=cid_ssl_name) + assert ssl_cip + assert self.dw_api.assert_login_access( + container_ip=ssl_cip, + username="postgres", + password=admin_password, + database="postgres", + expected_success=True, + ) + + output = self.dw_api.postgresql_cmd( + container_ip=ssl_cip, + container_id=VARS.IMAGE_NAME, + username="postgres", + password=admin_password, + database="postgres?sslmode=require", + sql_command="-At -c 'SELECT 1;'", + ) + assert re.search(r"1", output), f"1 not found in {output}" + + +class TestPostgreSQLS2IBakeDataContainer: + """ + Test PostgreSQL container configuration. + """ + + def setup_method(self): + """ + Setup the test environment. + """ + self.ssl_db = build_s2i_app( + app_path=VARS.TEST_DIR / "examples" / "s2i-dump-data" + ) + self.ssl_db.db_lib.db_type = "postgresql" + self.dw_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + + def teardown_method(self): + """ + Teardown the test environment. + """ + self.ssl_db.cleanup() + + def test_ssl(self): + """ + Test SSL. + """ + cid_ssl_name = "bake-data-test" + admin_password = "password" + + assert self.ssl_db.create_container( + cid_file_name=cid_ssl_name, + docker_args=[ + f"-e POSTGRESQL_ADMIN_PASSWORD={admin_password}", + ], + ) + assert self.dw_api.wait_for_database( + container_id=self.ssl_db.get_cid(cid_file_name=cid_ssl_name), + command="/usr/libexec/check-container", + ) + ssl_cip = self.ssl_db.get_cip(cid_file_name=cid_ssl_name) + assert ssl_cip + assert self.dw_api.assert_login_access( + container_ip=ssl_cip, + username="postgres", + password=admin_password, + database="postgres", + expected_success=True, + ) + + output = self.dw_api.postgresql_cmd( + container_ip=ssl_cip, + container_id=VARS.IMAGE_NAME, + username="postgres", + password=admin_password, + database="postgres", + sql_command="-At -c 'SELECT * FROM test;'", + ) + assert re.search(r"hello world", output), f"hello world not found in {output}" From a7a86fd8232c8c9575f101487265720e7642c107 Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 7 Jan 2026 14:10:18 +0100 Subject: [PATCH 3/4] Some refactoring caugh by real testing. Don not call the function twice Signed-off-by: Petr "Stone" Hracek --- test/test_container_basics.py | 23 +++++-- test/test_container_configuration.py | 81 ++++++------------------ test/test_container_general.py | 95 ++++++++++++++-------------- test/test_container_password.py | 42 +++++------- 4 files changed, 100 insertions(+), 141 deletions(-) diff --git a/test/test_container_basics.py b/test/test_container_basics.py index 20a376da..9715a646 100644 --- a/test/test_container_basics.py +++ b/test/test_container_basics.py @@ -1,6 +1,9 @@ +import shutil + from pathlib import Path from container_ci_suite.container_lib import ContainerTestLib +from container_ci_suite.utils import ContainerTestLibUtils from conftest import VARS, create_postgresql_temp_file @@ -23,15 +26,21 @@ class TestPostgreSQLBasicsContainer: """ def setup_method(self): + """ + Setup the test environment. + """ self.app_image = build_s2i_app(app_path=VARS.TEST_DIR / "test-app") self.app_image.db_lib.db_type = "postgresql" def teardown_method(self): + """ + Teardown the test environment. + """ self.app_image.cleanup() def test_s2i_usage(self): """ - Test container creation fails with invalid combinations of arguments. + Test container creation based on s2i technology. """ cid_config_build = "s2i_config_build" psql_password = "password" @@ -70,14 +79,16 @@ def test_s2i_usage(self): password=psql_backup_password, database="backup", ) - tmp_file = create_postgresql_temp_file() backup_user_script = ( VARS.TEST_DIR / "test-app" / "postgresql-init" / "backup_user.sh" ) - with open(backup_user_script, "r") as f: - backup_user_script_content = f.read() - with open(tmp_file, "w") as f: - f.write(backup_user_script_content) + tmp_file = create_postgresql_temp_file() + shutil.copy(backup_user_script, tmp_file) + ContainerTestLibUtils.commands_to_run( + commands_to_run=[ + f"setfacl -m u:26:rw- {tmp_file}", + ] + ) cid_s2i_test_mount = "s2i_test_mount" mount_point = "/opt/app-root/src/postgresql-init/add_backup_user.sh" assert self.app_image.create_container( diff --git a/test/test_container_configuration.py b/test/test_container_configuration.py index 3e012057..17c31768 100644 --- a/test/test_container_configuration.py +++ b/test/test_container_configuration.py @@ -18,6 +18,7 @@ def setup_method(self): """ self.db = ContainerTestLib(image_name=VARS.IMAGE_NAME, db_type="postgresql") self.db_api = DatabaseWrapper(image_name=VARS.IMAGE_NAME, db_type="postgresql") + self.volume_dir = create_postgresql_volume_dir() def teardown_method(self): """ @@ -142,16 +143,10 @@ def test_invalid_configuration_tests( "-e POSTGRESQL_ADMIN_PASSWORD=", ], [ - "-e POSTGRESQL_USER=user", - "-e POSTGRESQL_PASSWORD=pass", - "-e POSTGRESQL_DATABASE=db", - "-e POSTGRESQL_ADMIN_PASSWORD=", - ], - [ - "-e POSTGRESQL_USER=", - "-e POSTGRESQL_PASSWORD=", - "-e POSTGRESQL_DATABASE=", - '-e POSTGRESQL_ADMIN_PASSWORD="The @password"', + "", + "", + "", + '-e POSTGRESQL_ADMIN_PASSWORD="the @password"', ], [ '-e POSTGRESQL_USER="the user"', @@ -185,13 +180,21 @@ def test_configuration_hook(self): """ Test container creation fails with no arguments. """ - cid_file_name = "test_pg_hook" - volume_dir = create_postgresql_volume_dir() + self.shared_buffer_test("32MB") + self.shared_buffer_test("113MB") + self.shared_buffer_test("111MB") + + def shared_buffer_test(self, shared_buffer_value): + """ + Test shared buffer configuration. + """ + cid_file_name = f"test_pg_hook_{shared_buffer_value}" docker_args = [ "-e POSTGRESQL_ADMIN_PASSWORD=password", - "-e POSTGRESQL_SHARED_BUFFERS=32MB", - f"-v {volume_dir}:/opt/app-root/src:Z", + f"-e POSTGRESQL_SHARED_BUFFERS={shared_buffer_value}", + f"-v {self.volume_dir}:/opt/app-root/src:Z", ] + assert self.db.create_container( cid_file_name=cid_file_name, docker_args=docker_args, @@ -208,52 +211,6 @@ def test_configuration_hook(self): cid_file_name=cid, cmd='psql -tA -c "SHOW shared_buffers;"', ) - assert "32MB" in output, f"Shared buffers should be 32MB, but is {output}" - # Check that POSTGRESQL_SHARED_BUFFERS has effect. - docker_args = [ - "-e POSTGRESQL_ADMIN_PASSWORD=password", - "-e POSTGRESQL_SHARED_BUFFERS=113MB", - ] - cid_file_name2 = "test_pg_hook_2" - assert self.db.create_container( - cid_file_name=cid_file_name2, - docker_args=docker_args, - command="", + assert shared_buffer_value in output, ( + f"Shared buffers should be {shared_buffer_value}, but is {output}" ) - cid = self.db.get_cid(cid_file_name=cid_file_name2) - assert cid - cip = self.db.get_cip(cid_file_name=cid_file_name2) - assert cip - assert self.db_api.wait_for_database( - container_id=cid, command="/usr/libexec/check-container" - ) - output = PodmanCLIWrapper.podman_exec_shell_command( - cid_file_name=cid, - cmd='psql -tA -c "SHOW shared_buffers;"', - ) - assert "113MB" in output, f"Shared buffers should be 113MB, but is {output}" - # Check that volume has priority over POSTGRESQL_SHARED_BUFFERS. - cid_file_name3 = "test_pg_hook_3" - docker_args = [ - "-e POSTGRESQL_ADMIN_PASSWORD=password", - "-e POSTGRESQL_SHARED_BUFFERS=113MB", - f"-v {volume_dir}:/opt/app-root/src:Z", - ] - assert self.db.create_container( - cid_file_name=cid_file_name3, - docker_args=docker_args, - command="", - ) - cid = self.db.get_cid(cid_file_name=cid_file_name3) - assert cid - cip = self.db.get_cip(cid_file_name=cid_file_name3) - assert cip - assert self.db_api.wait_for_database( - container_id=cid, command="/usr/libexec/check-container" - ) - output = PodmanCLIWrapper.podman_exec_shell_command( - cid_file_name=cid, - cmd='psql -tA -c "SHOW shared_buffers;"', - ) - - assert "113MB" in output, f"Shared buffers should be 113MB, but is {output}" diff --git a/test/test_container_general.py b/test/test_container_general.py index 2d481382..e233f992 100644 --- a/test/test_container_general.py +++ b/test/test_container_general.py @@ -33,10 +33,10 @@ def teardown_method(self): [ ("", "user", "pass", "", "", "no_admin"), ("", "user1", "pass1", "", "r00t", "admin"), - # ("", "", "", "postgres", "r00t", "only_admin"), + ("", "", "", "postgres", "r00t", "only_admin"), ("-u 12345", "user2", "pass", "", "", "no_admin_altuid"), ("-u 12345", "user3", "pass1", "", "r00t", "admin_altuid"), - # ("-u 12345", "", "", "postgres", "r00t", "only_admin_altuid"), + ("-u 12345", "", "", "postgres", "r00t", "only_admin_altuid"), ], ) def test_run( @@ -60,28 +60,24 @@ def test_run( POSTGRESQL_SHARED_BUFFERS = "64MB" expected_success = False expected_admin_success = False + psql_user_arg = "" + psql_pwd_arg = "" + db_name_arg = "" + admin_root_password_arg = "" if psql_user != "": psql_user_arg = f"-e POSTGRESQL_USER={psql_user}" expected_success = True - else: - psql_user_arg = "" if psql_password: # empty password is allowed psql_pwd_arg = f"-e POSTGRESQL_PASSWORD={psql_password}" - else: - psql_pwd_arg = "" - if psql_database: - db_name = psql_database - else: - db_name = "db" + if psql_user and psql_password: + db_name_arg = "-e POSTGRESQL_DATABASE=db" if root_password == "r00t": admin_root_password_arg = f"-e POSTGRESQL_ADMIN_PASSWORD={root_password}" expected_admin_success = True - else: - admin_root_password_arg = "" docker_all_args = [ psql_user_arg, psql_pwd_arg, - f"-e POSTGRESQL_DATABASE={db_name}", + db_name_arg, admin_root_password_arg, f"-e POSTGRESQL_MAX_CONNECTIONS={POSTGRESQL_MAX_CONNECTIONS}", f"-e POSTGRESQL_MAX_PREPARED_TRANSACTIONS={POSTGRESQL_MAX_PREPARED_TRANSACTIONS}", @@ -115,30 +111,29 @@ def test_run( cmd="psql --version", ) assert VARS.VERSION in output - self.db_image.db_lib.assert_login_access( - container_ip=cip, - username=psql_user, - password=psql_password, - expected_success=expected_success, - ) - self.db_image.db_lib.assert_login_access( - container_ip=cip, - username=psql_user, - password=f"{psql_password}_foo", - expected_success=False, - ) - self.db_image.db_lib.assert_login_access( - container_ip=cip, - username="postgres", - password=root_password, - expected_success=expected_admin_success, - ) - self.db_image.db_lib.assert_login_access( - container_ip=cip, - username="postgres", - password=f"{root_password}_foo", - expected_success=False, - ) + access_output = True + if psql_database == "": + psql_database = "db" + for user, pwd, ret_value in [ + (psql_user, psql_password, expected_success), + (psql_user, f"{psql_password}_foo", False), + ("postgres", root_password, expected_admin_success), + ("postgres", f"{root_password}_foo", False), + ]: + test_assert = self.db_image.db_lib.assert_login_access( + container_ip=cip, + username=user, + password=pwd, + expected_success=ret_value, + database=psql_database, + ) + if not test_assert: + print( + f"Login access failed for {user}:{pwd} with expected success {ret_value}" + ) + access_output = False + break + assert access_output, "Login access failed for above results" assert self.db_image.db_lib.assert_local_access(container_id=cid) output = PodmanCLIWrapper.podman_exec_shell_command( cid_file_name=cid, @@ -154,24 +149,30 @@ def test_run( assert re.search(word, output), f"Word {word} not found in {output}" # test_postgresql if test_name == "admin": - psql_user = "postgres" - psql_password = root_password - psql_database = "postgres" output = self.db_api.run_sql_command( container_ip=cip, - username=psql_user, - password=psql_password, + username="postgres", + password=root_password, container_id=VARS.IMAGE_NAME, - database=db_name, + database="postgres", sql_cmd="-At -c 'CREATE EXTENSION \"uuid-ossp\";'", expected_output="CREATE EXTENSION", ) + if psql_password == "": + psql_password = root_password + + self.database_test(cip, psql_user, psql_password, psql_database) + + def database_test(self, cip, psql_user, psql_password, psql_database): + """ + Test PostgreSQL database creation. + """ output = self.db_api.run_sql_command( container_ip=cip, username=psql_user, password=psql_password, container_id=VARS.IMAGE_NAME, - database=db_name, + database=psql_database, sql_cmd='-At -c "CREATE TABLE tbl (a integer, b integer);"', expected_output="CREATE TABLE", ) @@ -181,7 +182,7 @@ def test_run( username=psql_user, password=psql_password, container_id=VARS.IMAGE_NAME, - database=db_name, + database=psql_database, sql_cmd=[ '-At -c "INSERT INTO tbl VALUES (1, 2);"', '-At -c "INSERT INTO tbl VALUES (3, 4);"', @@ -194,7 +195,7 @@ def test_run( username=psql_user, password=psql_password, container_id=VARS.IMAGE_NAME, - database=db_name, + database=psql_database, sql_cmd='-At -c "SELECT * FROM tbl;"', ) words = [ @@ -209,7 +210,7 @@ def test_run( username=psql_user, password=psql_password, container_id=VARS.IMAGE_NAME, - database=db_name, + database=psql_database, sql_cmd='-At -c "DROP TABLE tbl;"', expected_output="DROP TABLE", ) diff --git a/test/test_container_password.py b/test/test_container_password.py index 29dd319f..e076fd63 100644 --- a/test/test_container_password.py +++ b/test/test_container_password.py @@ -64,13 +64,13 @@ def test_password_change(self): ) cid1 = self.pwd_change.get_cid(cid_file_name=cid_file_name1) assert cid1 - self.pwd_change.db_lib.assert_login_access( + assert self.pwd_change.db_lib.assert_login_access( container_ip=cip1, username=username, password=password, expected_success=True, ) - self.pwd_change.db_lib.assert_login_access( + assert self.pwd_change.db_lib.assert_login_access( container_ip=cip1, username="postgres", password=admin_password, @@ -135,36 +135,26 @@ def test_password_change(self): ) cip_new = self.pwd_change.get_cip(cid_file_name=cid_file_name_new) assert cip_new + assert self.pwd_change.test_db_connection( container_ip=cip_new, username=username, password=new_password, max_attempts=10, ) - self.pwd_change.db_lib.assert_login_access( - container_ip=cip_new, - username=username, - password=new_password, - expected_success=True, - ) - self.pwd_change.db_lib.assert_login_access( - container_ip=cip_new, - username=username, - password=password, - expected_success=False, - ) - self.pwd_change.db_lib.assert_login_access( - container_ip=cip_new, - username="postgres", - password=new_admin_password, - expected_success=True, - ) - self.pwd_change.db_lib.assert_login_access( - container_ip=cip_new, - username="postgres", - password=admin_password, - expected_success=False, - ) + for user, pwd, ret_value in [ + (username, new_password, True), + (username, password, False), + ("postgres", new_admin_password, True), + ("postgres", "admin_password", False), + ]: + assert self.pwd_change.db_lib.assert_login_access( + container_ip=cip_new, + username=user, + password=pwd, + expected_success=ret_value, + ) + output = self.dw_api.run_sql_command( container_ip=cip_new, username=username, From 8f8b048ca8565f136572f59b35ec9e53c7a30f3e Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Mon, 12 Jan 2026 14:40:06 +0100 Subject: [PATCH 4/4] Add testing of database for assert_container_success function Signed-off-by: Petr "Stone" Hracek --- test/test_container_configuration.py | 83 ++++++++++++++++++++-------- test/test_container_extensions.py | 4 -- test/test_container_logging.py | 2 - 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/test/test_container_configuration.py b/test/test_container_configuration.py index 17c31768..41c6a32c 100644 --- a/test/test_container_configuration.py +++ b/test/test_container_configuration.py @@ -125,34 +125,34 @@ def test_invalid_configuration_tests( "psql_user, psql_password, psql_database, psql_admin_password", [ [ - "-e POSTGRESQL_USER=user", - "-e POSTGRESQL_PASSWORD=", - "-e POSTGRESQL_DATABASE=db", - "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + "user", + "pass", + "db", + "admin_pass", ], [ - "-e POSTGRESQL_USER=user", - "-e POSTGRESQL_PASSWORD=pass", - "-e POSTGRESQL_DATABASE=9invalid", - "-e POSTGRESQL_ADMIN_PASSWORD=admin_pass", + "user", + "pass", + "9invalid", + "admin_pass", ], [ - "-e POSTGRESQL_USER=user", - "-e POSTGRESQL_PASSWORD=pass", - "-e POSTGRESQL_DATABASE=db", - "-e POSTGRESQL_ADMIN_PASSWORD=", + "user", + "pass", + "db", + "", ], [ "", "", "", - '-e POSTGRESQL_ADMIN_PASSWORD="the @password"', + '"the @password"', ], [ - '-e POSTGRESQL_USER="the user"', - '-e POSTGRESQL_PASSWORD="the pass"', - '-e POSTGRESQL_DATABASE="the db"', - "-e POSTGRESQL_ADMIN_PASSWORD=", + '"the user"', + '"the pass"', + '"the db"', + "", ], ], ) @@ -166,15 +166,52 @@ def test_correct_configuration_tests( """ Test correct configuration combinations for PostgreSQL container. """ + psql_admin_password_arg = "" + psql_user_arg = "" + psql_password_arg = "" + psql_database_arg = "" + if psql_user: + psql_user_arg = f"-e POSTGRESQL_USER={psql_user}" + if psql_password: + psql_password_arg = f"-e POSTGRESQL_PASSWORD={psql_password}" + if psql_database: + psql_database_arg = f"-e POSTGRESQL_DATABASE={psql_database}" + if psql_admin_password: + psql_admin_password_arg = ( + f"-e POSTGRESQL_ADMIN_PASSWORD={psql_admin_password}" + ) + container_args = [ + psql_user_arg, + psql_password_arg, + psql_database_arg, + psql_admin_password_arg, + ] assert self.db.assert_container_creation_succeeds( - container_args=[ - psql_user, - psql_password, - psql_database, - psql_admin_password, - ], + container_args=container_args, command="", ) + cid_file_name = "cid_success_test" + assert self.db.create_container( + cid_file_name=cid_file_name, + container_args=container_args, + command="", + ) + cip = self.db.get_cip(cid_file_name=cid_file_name) + assert cip + if psql_user and psql_password: + assert self.db.test_db_connection( + container_ip=cip, + username=psql_user, + password=psql_password, + database=psql_database, + ) + if psql_admin_password: + assert self.db.test_db_connection( + container_ip=cip, + username="postgres", + password=psql_admin_password, + database=psql_database, + ) def test_configuration_hook(self): """ diff --git a/test/test_container_extensions.py b/test/test_container_extensions.py index 8c9d0c8f..cb4b7ac7 100644 --- a/test/test_container_extensions.py +++ b/test/test_container_extensions.py @@ -79,8 +79,6 @@ def test_pgaudit_extension_installation(self, env_load): docker_args=docker_args, command="", ) - cip = self.db.get_cip(cid_file_name=cid_file_name) - assert cip cid = self.db.get_cid(cid_file_name=cid_file_name) assert cid assert self.db_api.wait_for_database( @@ -151,8 +149,6 @@ def test_pgvector(self): docker_args=docker_args, command="", ) - cip = self.db.get_cip(cid_file_name=cid_file_name) - assert cip cid = self.db.get_cid(cid_file_name=cid_file_name) assert cid assert self.db_api.wait_for_database( diff --git a/test/test_container_logging.py b/test/test_container_logging.py index 853c70aa..ba2df8c6 100644 --- a/test/test_container_logging.py +++ b/test/test_container_logging.py @@ -44,8 +44,6 @@ def test_logging_destination(self): docker_args=docker_args, command="", ) - cip = self.db.get_cip(cid_file_name=cid_file_name) - assert cip cid = self.db.get_cid(cid_file_name=cid_file_name) assert cid assert self.db_api.wait_for_database(