Skip to content

Add tests for postgres db#1098

Merged
sheltoncyril merged 10 commits intoopendatahub-io:mainfrom
dbasunag:postgres
Feb 11, 2026
Merged

Add tests for postgres db#1098
sheltoncyril merged 10 commits intoopendatahub-io:mainfrom
dbasunag:postgres

Conversation

@dbasunag
Copy link
Copy Markdown
Collaborator

@dbasunag dbasunag commented Feb 9, 2026

Description

How Has This Been Tested?

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • Tests

    • Broadened model registry tests to exercise multiple DB backends (Postgres, MariaDB, MySQL); added backend-agnostic SSL/CA test flows, updated parametrization, marks, and test fixtures.
  • Chores

    • Generalized test utilities and fixtures for external DB support, unified cert/volume/deployment handling across backends, and added Postgres port mapping (5432) for tests.

@dbasunag dbasunag requested review from fege and lugi0 as code owners February 9, 2026 21:28
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Generalizes model-registry tests and helpers from MySQL-only to multi-backend external DB support (mysql/mariadb and postgres): adds Postgres port, renames/refactors DB helpers and fixtures (e.g., get_mysql_configget_external_db_config), and parameterizes SSL/deployment/test fixtures by db_backend.

Changes

Cohort / File(s) Summary
Port Configuration
tests/model_registry/constants.py
Added PostgreSQL port mapping: "postgres": 5432 to PORT_MAP.
Core utils — multi-backend DB support
tests/model_registry/utils.py
Large refactor: introduced backend-aware helpers (get_database_volumes, get_database_volume_mounts, get_database_image, get_database_health_probes, get_database_env_vars), added get_external_db_config (renamed from get_mysql_config), and updated deployment/service builders to accept db_backend, adapting env, images, ports, probes, volumes, and mounts.
RBAC util import updates
tests/model_registry/model_registry/rbac/multiple_instance_utils.py
Replaced import/call of get_mysql_config with get_external_db_config in instance parameter construction.
REST API conftest — backend-agnostic SSL fixtures
tests/model_registry/model_registry/rest_api/conftest.py
Generalized MySQL-specific fixtures to external-DB variants: added db_backend_under_test, external_db_template_with_ca, external_db_ssl_artifact_paths, external_db_ssl_secrets, patch_external_deployment_with_ssl_ca, deploy_secure_db_mr; replaced MySQL cert/configmap/secret names and helpers (add_mysql_certs_volumes_to_deploymentadd_db_certs_volumes_to_deployment).
REST API tests — parametrization and names
tests/model_registry/model_registry/rest_api/test_model_registry_rest_api.py
Adjusted test parametrization to exercise postgres/mariadb/default cases and updated marks for affected parameters.
Secure DB tests — backend-agnosticization
tests/model_registry/model_registry/rest_api/test_model_registry_secure_db.py
Parameterized secure-DB tests over db_backend_under_test, replaced MySQL-only fixtures with generalized ones (deploy_secure_db_mr, patch_external_deployment_with_ssl_ca), and updated CA/secret/configmap references and assertion/log messages to include backend context.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Utilities

Suggested reviewers

  • lugi0
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add tests for postgres db' directly reflects the main objective: expanding test coverage to include PostgreSQL database backend support alongside existing MySQL/MariaDB tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Feb 9, 2026

The following are automatically added/executed:

  • PR size label.
  • Run pre-commit
  • Run tox
  • Add PR author as the PR assignee
  • Build image based on the PR

Available user actions:

  • To mark a PR as WIP, add /wip in a comment. To remove it from the PR comment /wip cancel to the PR.
  • To block merging of a PR, add /hold in a comment. To un-block merging of PR comment /hold cancel.
  • To mark a PR as approved, add /lgtm in a comment. To remove, add /lgtm cancel.
    lgtm label removed on each new commit push.
  • To mark PR as verified comment /verified to the PR, to un-verify comment /verified cancel to the PR.
    verified label removed on each new commit push.
  • To Cherry-pick a merged PR /cherry-pick <target_branch_name> to the PR. If <target_branch_name> is valid,
    and the current PR is merged, a cherry-picked PR would be created and linked to the current PR.
  • To build and push image to quay, add /build-push-pr-image in a comment. This would create an image with tag
    pr-<pr_number> to quay repository. This image tag, however would be deleted on PR merge or close action.
Supported labels

{'/lgtm', '/wip', '/hold', '/cherry-pick', '/verified', '/build-push-pr-image'}

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-1098: success.
Status of pushing tag pr-1098 to image registry: success.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
tests/model_registry/model_registry/rest_api/test_model_registry_secure_db.py (2)

32-46: ⚠️ Potential issue | 🟡 Minor

ca_mount_path: "/etc/mysql/ssl" is MySQL-specific but will be used for PostgreSQL tests too.

Since the class is now parameterized over both mysql and postgres backends, using a hardcoded /etc/mysql/ssl mount path for the CA in both test methods (lines 38 and 87) will produce a misleading MySQL-centric path inside a PostgreSQL container. Consider parameterizing the mount path based on the backend or using a backend-neutral path like /etc/db/ssl.


103-130: ⚠️ Potential issue | 🟡 Minor

Missing docstring on test_register_model_with_valid_ca.

As per coding guidelines, every test must have a docstring explaining what it tests, preferably in Given-When-Then format.

Suggested docstring
     def test_register_model_with_valid_ca(
         self: Self,
         admin_client: DynamicClient,
         model_registry_namespace: str,
         model_registry_rest_headers: dict[str, str],
         local_ca_bundle: str,
         deploy_secure_db_mr: ModelRegistry,
         model_data_for_test: dict[str, Any],
         db_backend_under_test: str,
     ):
+        """
+        Test that model registration succeeds when the Model Registry is deployed
+        with a valid CA certificate for the secure database backend.
+
+        Given: A Model Registry deployed with a valid SSL CA for the db_backend_under_test.
+        When: A model is registered via the REST API using the valid CA bundle.
+        Then: The registration succeeds and the returned model attributes match the expected data.
+        """
         service = get_mr_service_by_label(

As per coding guidelines: tests/**/*.py: Every test MUST have a docstring explaining what it tests.

tests/model_registry/utils.py (1)

525-563: ⚠️ Potential issue | 🟡 Minor

Simplify annotation template to match codebase pattern.

The f-string is unnecessarily complex for a template string with only literal characters. Other instances in the codebase (conftest.py:75, rbac/multiple_instance_utils.py:43) use a plain raw string: r"mysql://{.spec.clusterIP}:{.spec.ports[?(.name==\mysql\)].port}". Change line 536 to use the same pattern but parameterized for the dynamic service_port_name:

service_uri = rf"{service_port_name}://{{{.spec.clusterIP}}}:{{{.spec.ports[?(.name==\{service_port_name}\)].port}}}"

Or refactor to a plain raw string with format substitution:

service_uri = f"{service_port_name}://{{.spec.clusterIP}}:{{.spec.ports[?(.name==\\{service_port_name}\\)].port}}"

Note: The backslash escapes in the JSONPath filter (e.g., \{, \)) are consistent with existing usages in the codebase, though they should be verified against OpenShift template syntax specifications.

🤖 Fix all issues with AI agents
In `@tests/model_registry/model_registry/rest_api/conftest.py`:
- Around line 135-173: external_db_template_with_ca currently builds
postgres_ssl_args and calls
db_deployment_template["spec"]["containers"][0].get("args", []).extend(...),
which mutates a temporary list and never writes it back; fix by ensuring the
container has an "args" list before extending it (e.g., use container =
db_deployment_template["spec"]["containers"][0]; container.setdefault("args",
[]) and then extend with postgres_ssl_args) so the args are persisted in the
template returned by external_db_template_with_ca (refer to
get_model_registry_deployment_template_dict, CA_FILE_PATH, CA_MOUNT_PATH,
CA_CONFIGMAP_NAME).
- Around line 286-289: The code uses next(container for container in
spec["containers"] if container["name"] == db_backend_under_test) which will
raise StopIteration before the subsequent assert can run; change to use
next((container for container in spec["containers"] if container["name"] ==
db_backend_under_test), None) so db_container may be None and the assert
db_container is not None, f"{db_backend_under_test} container not found" will
produce the intended error message; update the reference where db_container is
defined (in the block handling
model_registry_db_deployments[0].instance.to_dict()) accordingly.
- Around line 148-163: The PostgreSQL SSL file paths in the fixture
(postgres_ssl_args in tests/model_registry/model_registry/rest_api/conftest.py)
differ from those used in apply_mysql_args_and_volume_mounts in
tests/model_registry/utils.py; update one side so both use the same paths (e.g.,
set postgres_ssl_args entries ssl_cert_file, ssl_key_file, and ssl_ca_file to
the same /etc/ssl-certs, /etc/ssl-keys, /etc/ssl-ca paths used by
apply_mysql_args_and_volume_mounts or vice versa) and ensure the final values
are applied to db_deployment_template["spec"]["containers"][0]["args"]
consistently.

In `@tests/model_registry/utils.py`:
- Around line 42-45: The POSTGRES_DB_IMAGE constant currently uses "postgres:16"
instead of the commented RHEL image; restore the RHEL image value by setting
POSTGRES_DB_IMAGE to the original RHEL URI (the removed sha256 pinned string)
or, if that image fails in CI, add an explicit fallback mechanism and a clear
TODO referencing an issue/bug ID: e.g., set POSTGRES_DB_IMAGE to the RHEL URI
from the commented line, or set it from an environment variable with the RHEL
URI as the default, and add a short comment that documents the CI failure and
links the issue number so the RHEL image replacement is tracked (refer to
POSTGRES_DB_IMAGE to locate and change the constant).
🧹 Nitpick comments (3)
tests/model_registry/utils.py (1)

391-466: Function name apply_mysql_args_and_volume_mounts is misleading now that it handles both MySQL and PostgreSQL.

The function body branches on db_backend to support both MySQL and PostgreSQL, but the name still says "mysql". This should be renamed for consistency with the other renamed functions (e.g., add_db_certs_volumes_to_deployment, get_external_db_config).

Suggested rename
-def apply_mysql_args_and_volume_mounts(
+def apply_db_args_and_volume_mounts(
     db_container: dict[str, Any],
     ca_configmap_name: str,
     ca_mount_path: str,
     db_backend: str,
 ) -> dict[str, Any]:
     """
-    Applies the database args and volume mounts to the database container.
+    Applies backend-specific SSL args and volume mounts to the database container.

Note: This rename must also be applied to the import in conftest.py (line 17) and any other callers.

tests/model_registry/model_registry/rest_api/conftest.py (2)

321-362: SSL secrets use manual create()/delete() instead of context managers for lifecycle management.

Per coding guidelines, Kubernetes resource lifecycle should use context managers to ensure cleanup. The create_k8s_secret utility calls .create() directly and the teardown relies on manual .delete() calls. If an error occurs between creation and teardown, secrets may leak.

Consider wrapping in context managers or using the with pattern. If create_k8s_secret can't be changed, this is a deferred improvement.

As per coding guidelines: tests/**/conftest.py: Use context managers for resource lifecycle management in fixtures.


268-307: Fixture name patch_external_deployment_with_ssl_ca uses a verb — guideline recommends nouns.

Similarly, deploy_secure_db_mr (line 177) uses a verb. Consider noun-based names like external_deployment_with_ssl_ca and secure_db_mr respectively.

As per coding guidelines: tests/**/conftest.py: Fixture names MUST be nouns: storage_secret not create_secret.

Comment thread tests/model_registry/model_registry/rest_api/conftest.py
Comment thread tests/model_registry/model_registry/rest_api/conftest.py
Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
Comment thread tests/model_registry/utils.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
tests/model_registry/utils.py (1)

570-570: ⚠️ Potential issue | 🟡 Minor

Incorrect return type annotation: list[Service] should be list[ConfigMap].

get_mr_configmap_objects returns a list of ConfigMap objects, not Service.

Proposed fix
-) -> list[Service]:
+) -> list[ConfigMap]:
tests/model_registry/model_registry/rest_api/test_model_registry_rest_api.py (1)

152-169: ⚠️ Potential issue | 🟡 Minor

Missing docstring on test_default_postgres_db_pod_log.

Per coding guidelines, every test must have a docstring explaining what it tests. This new test validates the default Postgres pod log contains the expected connection string but lacks a docstring.

Proposed fix
     def test_default_postgres_db_pod_log(
         self: Self,
         skip_if_not_default_db: None,
         admin_client: DynamicClient,
         model_registry_namespace: str,
         model_registry_default_postgres_deployment_match_label: dict[str, str],
     ):
+        """
+        Test that the default postgres pod log contains the expected connection string,
+        confirming the database is accepting connections.
+        """
         label_selector = ",".join([
tests/model_registry/model_registry/rest_api/test_model_registry_secure_db.py (2)

103-130: ⚠️ Potential issue | 🟡 Minor

Missing docstring on test_register_model_with_valid_ca.

Per coding guidelines, every test must have a docstring. This test validates successful model registration with a valid CA certificate over a secure DB connection.


35-43: ⚠️ Potential issue | 🟡 Minor

Use a backend-neutral mount path instead of /etc/mysql/ssl.

The parametrization applies to both MySQL and PostgreSQL backends (via class-level db_backend_under_test), but the mount path is hardcoded with "mysql". The add_db_container_certificates() function in utils.py uses the same ca_mount_path for both backends without differentiating, and volumeMounts apply identically regardless of backend type. While the path itself is functionally correct for both, the naming is misleading. Consider /etc/db/ssl or /etc/ssl to reflect its backend-agnostic usage.

🤖 Fix all issues with AI agents
In `@tests/model_registry/model_registry/rest_api/conftest.py`:
- Around line 283-284: The local variables CA_CONFIGMAP_NAME and CA_MOUNT_PATH
in the fixture are shadowing the module-level constants imported from
tests.model_registry.constants; rename the local variables to lowercase (e.g.,
ca_configmap_name and ca_mount_path) in the fixture that reads request.param,
and update all subsequent references (the uses of CA_CONFIGMAP_NAME and
CA_MOUNT_PATH later in that function) to the new lowercase names so the
module-level imports remain unshadowed and intent is clear.
🧹 Nitpick comments (3)
tests/model_registry/utils.py (1)

388-393: Function name apply_mysql_args_and_volume_mounts is misleading — it now handles Postgres too.

The function was generalized to support both MySQL and PostgreSQL backends via the db_backend parameter, but the name still says "mysql". Consider renaming to apply_db_args_and_volume_mounts for consistency with the rest of the refactor (e.g., add_db_certs_volumes_to_deployment).

tests/model_registry/model_registry/rest_api/conftest.py (2)

177-183: Fixture name deploy_secure_db_mr is verb-based.

As per coding guidelines, fixture names should be nouns (e.g., secure_db_model_registry), not verbs/actions. Similarly, patch_external_deployment_with_ssl_ca (line 268) is verb-based. As per coding guidelines: "Fixture names MUST be nouns: storage_secret not create_secret".


321-362: external_db_ssl_secrets manually deletes secrets instead of using a context manager.

The fixture creates secrets via create_k8s_secret and manually deletes them in teardown. Per coding guidelines, resource lifecycle should use context managers to ensure cleanup. If create_k8s_secret doesn't support the context manager protocol, this may be a limitation, but it's worth noting.

Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/model_registry/utils.py (1)

565-572: ⚠️ Potential issue | 🟡 Minor

Incorrect return type annotation: list[Service] should be list[ConfigMap].

The function returns a list of ConfigMap objects, but the return type is annotated as list[Service].

Proposed fix
 def get_mr_configmap_objects(
     base_name: str,
     namespace: str,
     client: DynamicClient,
     teardown_resources: bool,
     num: int,
     db_backend: str,
-) -> list[Service]:
+) -> list[ConfigMap]:
🧹 Nitpick comments (3)
tests/model_registry/utils.py (3)

390-395: Function name apply_mysql_args_and_volume_mounts is misleading — it now handles Postgres too.

The function was extended to support the postgres backend (line 432), but the name still says "mysql". Consider renaming to something backend-agnostic like apply_db_args_and_volume_mounts for consistency with the other refactored helpers (e.g., add_db_certs_volumes_to_deployment).


88-115: New backend-dispatch helpers look good overall.

The factored-out helpers (get_database_volumes, get_database_volume_mounts, get_database_image, get_database_health_probes, get_database_env_vars) cleanly separate backend-specific concerns. One minor observation: the db_backend string is checked via raw string comparisons ("postgres", "mariadb", "mysql") throughout. If a typo or unexpected value is passed, these functions silently fall through to the MySQL default. Consider adding a guard or using an enum/constant set for the valid backend values to catch misconfiguration early.

Also applies to: 118-142, 145-153, 156-209, 212-258


353-387: add_db_certs_volumes_to_deployment silently no-ops for mariadb backend.

The function handles "mysql" and "postgres" but has no branch for "mariadb". If MariaDB SSL tests are added later, this will silently return the original volumes without any cert mounts. A brief comment noting this is intentional (or a ValueError for unsupported backends) would prevent confusion.

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-1098: success.
Status of pushing tag pr-1098 to image registry: success.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@tests/model_registry/model_registry/rest_api/conftest.py`:
- Line 284: The fixture currently sets a MySQL-specific default ca_mount_path
("/etc/mysql/ssl") which is incorrect for other backends; change the assignment
to inspect request.param.get("backend") and choose a backend-appropriate default
(e.g., use "/etc/mysql/ssl" for mysql, "/etc/postgres/ssl" for postgres) or fall
back to a neutral path like "/etc/ssl/certs" (or None) when backend is
unspecified, by replacing the direct default of ca_mount_path with logic that
derives it from request.param and assigning to ca_mount_path accordingly.
- Around line 288-289: The assertion is wrong because db_containers is a list
(never None); change the check to assert that the list is non-empty (e.g.,
assert db_containers or len(db_containers) > 0) and include a clear message
using db_backend_under_test so failures show which backend was not found; update
the code around the db_containers = [container for container in
spec["containers"] if container["name"] == db_backend_under_test] line and the
following assertion to validate emptiness instead of None and provide a helpful
error message.
🧹 Nitpick comments (1)
tests/model_registry/model_registry/rest_api/conftest.py (1)

330-362: Consider using context managers for secret lifecycle management.

The secrets are created with create_k8s_secret and manually deleted in teardown. Per coding guidelines, fixtures should "use context managers for resource lifecycle management." If the Secret resource supports with (as ConfigMap does elsewhere in this file), that would simplify cleanup and ensure it happens even on exceptions.

Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-1098: success.
Status of pushing tag pr-1098 to image registry: success.

Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
Comment thread tests/model_registry/model_registry/rest_api/conftest.py
Comment thread tests/model_registry/model_registry/rest_api/conftest.py Outdated
Comment thread tests/model_registry/model_registry/rest_api/conftest.py
Comment thread tests/model_registry/model_registry/rest_api/conftest.py
Comment thread tests/model_registry/utils.py
Comment thread tests/model_registry/utils.py Outdated
Comment thread tests/model_registry/utils.py
Comment thread tests/model_registry/utils.py
Comment thread tests/model_registry/utils.py
@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-1098: success.
Status of pushing tag pr-1098 to image registry: success.

fege
fege previously approved these changes Feb 11, 2026
Copy link
Copy Markdown
Contributor

@fege fege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@dbasunag
Copy link
Copy Markdown
Collaborator Author

/build-push-pr-image

@github-actions
Copy link
Copy Markdown

Status of building tag pr-1098: success.
Status of pushing tag pr-1098 to image registry: success.

@dbasunag dbasunag requested a review from fege February 11, 2026 15:53
Copy link
Copy Markdown
Contributor

@fege fege left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

Copy link
Copy Markdown
Contributor

@sheltoncyril sheltoncyril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@sheltoncyril sheltoncyril merged commit 1ca0054 into opendatahub-io:main Feb 11, 2026
10 checks passed
@github-actions
Copy link
Copy Markdown

Status of building tag latest: success.
Status of pushing tag latest to image registry: success.

@dbasunag dbasunag deleted the postgres branch March 19, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants