Skip to content

Conversation

@jiaoshuntian
Copy link
Collaborator

@jiaoshuntian jiaoshuntian commented Nov 20, 2025

Checklist:

  • Have you added an explanation of what your changes do and why you'd like them to be included?
  • Have you updated or added documentation for the change, as applicable?
  • Have you tested your changes on all related environments with successful results, as applicable?
    • Have you added automated tests?

Type of Changes:

  • New feature
  • Bug fix
  • Documentation
  • Testing enhancement
  • Other

What is the current behavior (link to any open issues here)?

What is the new behavior (if this is a feature change)?

  • Breaking change (fix or feature that would cause existing functionality to change)

Other Information:

Summary by CodeRabbit

  • New Features

    • Added support for PostgreSQL and IvorySQL version 18.
  • Chores

    • Upgraded operator to v5.0 and updated component images (pgBackRest 2.56.0, pgAdmin 9.9, PostGIS 3.5, pgExporter, PgBouncer, etc.).
    • Updated test and upgrade scenarios to target the new versions.
  • Bug Fixes / Behavior

    • Simplified environment preload configuration and aligned backup tooling to the newer PostgreSQL/pgBackRest version.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

Upgrades the operator from v4.0→v5.0 and broadens supported PostgreSQL/IvorySQL major version from 17→18. Changes touch container image tags and env vars, CRD/type validation limits, pgBackRest version flags and tests, kustomize manifests, KUTTL test fixtures/workflows, and release notes.

Changes

Cohort / File(s) Summary
CRD & API types
config/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml, config/crd/bases/ivory-operator.ivorysql.org_ivyupgrades.yaml, examples/kustomize/install/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml, pkg/apis/ivory-operator.ivorysql.org/v1beta1/ivorycluster_types.go, pkg/apis/ivory-operator.ivorysql.org/v1beta1/pgupgrade_types.go
Bumped validation maxima from 17 → 18 for PostgresVersion, fromIvoryVersion, and toIvoryVersion in CRDs and Go kubebuilder tags.
Operator images / kustomize
config/default/kustomization.yaml, config/singlenamespace/kustomization.yaml, examples/kustomize/install/default/kustomization.yaml, examples/kustomize/install/singlenamespace/kustomization.yaml
Updated ivory-operator image tag from v4.0v5.0 in kustomize manifests.
Manager env / example manager
config/manager/manager.yaml, examples/kustomize/install/manager/manager.yaml
Replaced/renamed RELATED_IMAGE variables (IVORY_16→IVORY_18), updated RELATED_IMAGE_* tags (pgbackrest, pgadmin, pgbouncer, pgexporter, postgis) to new v5.0-style image tags.
pgBackRest config & invocation
internal/pgbackrest/config.go, internal/pgbackrest/pgbackrest.go, internal/pgbackrest/config_test.go, internal/pgbackrest/pgbackrest_test.go, internal/controller/ivorycluster/pgbackrest_test.go
Changed pg-version-force from 17 → 18 in generated config and executed pgbackrest commands; updated tests to expect new value.
LD_PRELOAD / NSS wrapper
internal/controller/ivorycluster/util.go, internal/controller/ivorycluster/util_test.go
Simplified LD_PRELOAD to only include /usr/lib64/libnss_wrapper.so and adjusted related test expectation.
KUTTL / workflow & test fixtures
.github/workflows/test.yaml, testing/kuttl/e2e-other/exporter-upgrade/00--cluster.yaml, testing/kuttl/e2e-other/exporter-upgrade/02--update-cluster.yaml
Updated prefetch images, environment vars, KUTTL version references, and test cluster specs/images to use Ivory 5.0 / Postgres 18 / PostGIS 3.5 tags.
Release notes
ivyo_release_notes.md
Added IvorySQL Operator 5.0 release notes documenting component and plugin version upgrades.

Sequence Diagram(s)

(omitted — changes are configuration/version bumps and small invocations; control flow remained unchanged)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Attention areas:
    • CRD/schema and kubebuilder tag changes — ensure all schema locations and generated CRD files are consistent.
    • pgBackRest pg-version-force change — confirm compatibility with pgBackRest and any upgrade/stanza logic.
    • Manager RELATED_IMAGE renames — verify deployment environment uses matching env var names and images.
    • KUTTL/workflow image and version bumps — ensure images/tags exist and tests remain valid.
    • LD_PRELOAD simplification — validate runtime behavior in containers that previously relied on removed libraries.

Possibly related PRs

  • ivorysql opertor V4 release #79 — modifies similar areas (CRDs, manager env vars, pgBackRest config, kustomize manifests, NSS wrapper handling); likely a related coordinated version bump.

Poem

🐰 From four to five I nimbly bound,
Eighteen now sits on the versioned ground.
Tags updated, configs aligned with care,
Tests adjusted — a hop through the air.
Small paws, big changes, carrots to share. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is entirely unchecked template boilerplate with no actual content filled in; all required sections lack substantive information about changes, rationale, testing, and type of change. Complete the description by checking relevant boxes, explaining what changes do and why, documenting updates, confirming testing results, and specifying the type of change (e.g., Testing enhancement for version bumps).
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'update for ivyo 5.0' is vague and generic, using non-descriptive phrasing that doesn't convey meaningful information about the specific changes made. Revise the title to be more specific and descriptive, such as 'Upgrade IvorySQL Operator to version 5.0 with database and component updates' to better summarize the main changes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d242d09 and e67969d.

📒 Files selected for processing (2)
  • internal/controller/ivorycluster/util.go (2 hunks)
  • internal/controller/ivorycluster/util_test.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: kuttl-k3d (v1.21)
  • GitHub Check: kuttl-k3d (v1.22)
  • GitHub Check: kuttl-k3d (v1.24)
  • GitHub Check: kuttl-k3d (v1.25)
  • GitHub Check: kuttl-k3d (v1.23)
  • GitHub Check: kubernetes-k3d (v1.28)
  • GitHub Check: kubernetes-k3d (v1.25)
🔇 Additional comments (2)
internal/controller/ivorycluster/util_test.go (1)

271-271: LGTM! Test expectation correctly updated.

The test expectation has been properly updated to match the new LD_PRELOAD value in util.go. The change is consistent with the implementation.

internal/controller/ivorycluster/util.go (1)

112-112: The LD_PRELOAD change appears intentional and correct—runtime verification of SSL/TLS functionality is needed.

Based on code analysis, the removal of libssl.so.1.1 and libcrypto.so.1.1 from LD_PRELOAD is intentional and consistent across the codebase:

  • util.go (lines 112 and 197) now sets LD_PRELOAD=/usr/lib64/libnss_wrapper.so without SSL libraries
  • Test expectations (util_test.go lines 271 and 277) align with this configuration
  • nss_wrapper purpose is user/group resolution for OpenShift compatibility, not SSL/TLS—it does not require SSL libraries in LD_PRELOAD
  • IvorySQL 5.0 requires OpenSSL ≥ 1.1.1, which will be available system-wide

The change is well-integrated and consistent. However, you should verify that SSL/TLS connections to the database function correctly in the v5.0 container environment, as this static analysis cannot confirm runtime behavior. If SSL/TLS connectivity issues arise, confirm the OpenSSL libraries are available in the container image.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

Copy link

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20a1255 and d242d09.

📒 Files selected for processing (20)
  • .github/workflows/test.yaml (4 hunks)
  • config/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml (1 hunks)
  • config/crd/bases/ivory-operator.ivorysql.org_ivyupgrades.yaml (2 hunks)
  • config/default/kustomization.yaml (1 hunks)
  • config/manager/manager.yaml (1 hunks)
  • config/singlenamespace/kustomization.yaml (1 hunks)
  • examples/kustomize/install/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml (1 hunks)
  • examples/kustomize/install/default/kustomization.yaml (1 hunks)
  • examples/kustomize/install/manager/manager.yaml (1 hunks)
  • examples/kustomize/install/singlenamespace/kustomization.yaml (1 hunks)
  • internal/controller/ivorycluster/pgbackrest_test.go (4 hunks)
  • internal/pgbackrest/config.go (1 hunks)
  • internal/pgbackrest/config_test.go (1 hunks)
  • internal/pgbackrest/pgbackrest.go (1 hunks)
  • internal/pgbackrest/pgbackrest_test.go (1 hunks)
  • ivyo_release_notes.md (1 hunks)
  • pkg/apis/ivory-operator.ivorysql.org/v1beta1/ivorycluster_types.go (1 hunks)
  • pkg/apis/ivory-operator.ivorysql.org/v1beta1/pgupgrade_types.go (2 hunks)
  • testing/kuttl/e2e-other/exporter-upgrade/00--cluster.yaml (1 hunks)
  • testing/kuttl/e2e-other/exporter-upgrade/02--update-cluster.yaml (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
ivyo_release_notes.md

49-49: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


50-50: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


51-51: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


52-52: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


53-53: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


55-55: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


55-55: Hard tabs
Column: 1

(MD010, no-hard-tabs)


56-56: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


56-56: Hard tabs
Column: 1

(MD010, no-hard-tabs)


57-57: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


57-57: Hard tabs
Column: 1

(MD010, no-hard-tabs)


58-58: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


58-58: Hard tabs
Column: 1

(MD010, no-hard-tabs)


59-59: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


59-59: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: go-test
🔇 Additional comments (21)
pkg/apis/ivory-operator.ivorysql.org/v1beta1/pgupgrade_types.go (1)

62-63: LGTM! Version validation extended to support IvorySQL 18.

The validation constraints have been correctly updated to allow upgrades to and from IvorySQL version 18, aligning with the operator's 5.0 release scope.

Also applies to: 73-74

config/singlenamespace/kustomization.yaml (1)

17-17: LGTM! Operator image tag updated to v5.0.

The image tag update aligns with the operator version upgrade.

.github/workflows/test.yaml (4)

67-69: LGTM! Test images updated to IvorySQL 5.0 series.

The prefetch images have been correctly updated to the latest 5.0-5.0-1 tag series.


101-106: LGTM! KUTTL test images updated to 5.0 release.

All component images (pgadmin, pgbackrest, pgbouncer, postgres-exporter, ivorysql, postgis) have been updated to the 5.0 series tags, ensuring test consistency with the operator upgrade.


121-127: LGTM! Environment variables updated to IvorySQL 18.

The RELATED_IMAGE environment variables have been correctly updated from version 17 to 18 and PostGIS from 3.4 to 3.5.


138-142: LGTM! KUTTL generation parameters updated to PostgreSQL 18.

Test generation variables have been updated to reflect PostgreSQL version 18 and PostGIS 3.5, aligning with the operator's expanded version support.

testing/kuttl/e2e-other/exporter-upgrade/00--cluster.yaml (1)

6-7: LGTM! Test cluster updated to PostgreSQL 18 and IvorySQL 5.0.

The exporter upgrade test has been correctly updated to use PostgreSQL version 18 with the corresponding 5.0-5.0-1 image tag.

config/default/kustomization.yaml (1)

15-15: LGTM! Default kustomization updated to v5.0.

The operator image tag has been correctly updated to v5.0, consistent with the version upgrade.

internal/pgbackrest/config_test.go (1)

156-156: LGTM! Test expectation updated to match implementation.

The test correctly expects pg-version-force = 18 in the generated pgBackRest configuration, matching the implementation change in internal/pgbackrest/pgbackrest.go.

examples/kustomize/install/default/kustomization.yaml (1)

16-16: LGTM: Image tag updated to v5.0.

The operator image tag has been correctly updated to align with the IvorySQL 5.0 upgrade.

testing/kuttl/e2e-other/exporter-upgrade/02--update-cluster.yaml (1)

6-7: LGTM: Test configuration updated for PostgreSQL 18.

The test configuration correctly reflects the version bump to PostgreSQL 18 and the corresponding IvorySQL 5.0 image.

internal/controller/ivorycluster/pgbackrest_test.go (1)

2105-2156: LGTM: Test expectations updated for PostgreSQL 18.

The test cases correctly verify that the generated pgBackRest configuration includes pg-version-force = 18, aligning with the changes in internal/pgbackrest/config.go.

config/crd/bases/ivory-operator.ivorysql.org_ivyupgrades.yaml (2)

860-862: LGTM: CRD validation updated to support PostgreSQL 18.

The fromIvoryVersion maximum constraint has been correctly increased to 18 to support upgrades from PostgreSQL 18.


939-941: LGTM: CRD validation updated to support PostgreSQL 18.

The toIvoryVersion maximum constraint has been correctly increased to 18 to support upgrades to PostgreSQL 18.

internal/pgbackrest/pgbackrest_test.go (1)

41-41: LGTM: Test updated to verify PostgreSQL version 18 parameter.

The expected command string correctly includes --pg-version-force=18, matching the implementation changes in the pgBackRest configuration generation.

examples/kustomize/install/singlenamespace/kustomization.yaml (1)

16-16: LGTM: Image tag updated to v5.0.

The operator image tag has been correctly updated for the single-namespace installation variant, maintaining consistency with the default installation configuration.

examples/kustomize/install/manager/manager.yaml (1)

29-32: LGTM: Environment variables and image tags updated consistently.

Verification confirms that no references to RELATED_IMAGE_IVORY_3 remain anywhere in the codebase. The rename to RELATED_IMAGE_IVORY_5 in examples/kustomize/install/manager/manager.yaml has been cleanly executed with matching image tag updates for both IvorySQL (5.0) and pgBackRest (2.56.0).

examples/kustomize/install/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml (1)

10468-10473: Version constraint update is consistent and valid across all related files.

Verification confirms the postgresVersion maximum constraint has been properly updated from 17 to 18 across all three critical layers:

  • Primary CRD (config/crd/bases/): maximum: 18 at line 10471
  • Go Validation (pkg/apis/): +kubebuilder:validation:Maximum=18 at line 126
  • Example/Kustomize (examples/kustomize/): maximum: 18 at line 10471
  • Tests: Both exporter-upgrade tests use postgresVersion: 18

All files are in sync and PostgreSQL 18 is a valid, released version.

config/crd/bases/ivory-operator.ivorysql.org_ivoryclusters.yaml (1)

10471-10471: Version constraint update verified as consistent across all files.

The postgresVersion maximum has been correctly updated to 18 in:

  • CRD base file: line 10471
  • Examples kustomize CRD: line 10471
  • Go type annotations: ivorycluster_types.go:126, pgupgrade_types.go:62, pgupgrade_types.go:73

All constraint sources are synchronized. The change properly supports the IvorySQL 5.0 upgrade.

config/manager/manager.yaml (2)

21-22: No action required—the operator code properly handles these environment variables.

The operator dynamically constructs environment variable names based on the PostgreSQL version (e.g., "RELATED_IMAGE_IVORY_" + fmt.Sprint(cluster.Spec.PostgresVersion)), not hardcoding specific versions. The manager.yaml changes define the available environment variables that the operator will discover at runtime. No orphaned references to old variable names exist in the codebase.

Likely an incorrect or invalid review comment.


24-24: Manual verification of Docker image tags required.

Unable to conclusively verify the Docker image tag availability through automated means. The registry cannot be accessed to confirm that these tags exist:

  • docker.io/ivorysql/pgadmin:ubi8-9.9-5.0-1
  • docker.io/ivorysql/pgbackrest:ubi8-2.56.0-5.0-1
  • docker.io/ivorysql/pgbouncer:ubi8-1.23.0-5.0-1
  • docker.io/ivorysql/postgres-exporter:ubi8-0.17.0-5.0-1

Please verify these tags exist in the Docker registry before merging by running: docker pull docker.io/ivorysql/<image>:<tag> for each image.

stanza.Set("pg1-port", fmt.Sprint(pgPort))
stanza.Set("pg1-socket-path", ivory.SocketDirectory)
stanza.Set("pg-version-force", "17")
stanza.Set("pg-version-force", "18")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Consider deriving the PostgreSQL version dynamically rather than hardcoding.

The pg-version-force parameter is now hardcoded to "18". This could cause issues if:

  • Different clusters run different PostgreSQL major versions
  • Future version upgrades require updating this hardcoded value in multiple places

Consider whether this should be derived from the cluster's actual PostgresVersion field or defined as a package-level constant.

Verify if there are other locations where PostgreSQL version 18 is hardcoded:


🏁 Script executed:

#!/bin/bash
# Search for hardcoded references to PostgreSQL version 18
rg -n '"18"' internal/pgbackrest/ --type go

Length of output: 71


I'll verify the scope and context of this hardcoding issue more thoroughly.








🏁 Script executed:

#!/bin/bash
# Search for all "18" references in the entire codebase
rg -n '"18"' --type go -C 2

Length of output: 357


🏁 Script executed:

#!/bin/bash
# Search for PostgresVersion usage in the codebase
rg -n 'PostgresVersion' --type go -C 2

Length of output: 13683


🏁 Script executed:

#!/bin/bash
# Get context around line 313 in config.go
sed -n '300,330p' internal/pgbackrest/config.go

Length of output: 961


🏁 Script executed:

#!/bin/bash
# Search for pg-version-force in the codebase to understand usage pattern
rg -n 'pg-version-force' --type go -C 2

Length of output: 5384


I need to see the complete function signature to determine if the cluster information is available.


---

🏁 Script executed:

```shell
#!/bin/bash
# Find the function definition containing line 313
sed -n '280,315p' internal/pgbackrest/config.go | head -50

Length of output: 1522


🏁 Script executed:

#!/bin/bash
# Get broader context to see function signature
sed -n '260,320p' internal/pgbackrest/config.go

Length of output: 2367


Now I need to find where this function is called to understand how to pass the PostgreSQL version.


---

🏁 Script executed:

```shell
#!/bin/bash
# Find all calls to populatePGInstanceConfigurationMap
rg -n 'populatePGInstanceConfigurationMap' --type go -B 2 -A 5

Length of output: 1241


Hardcode at line 313 needs to be replaced with dynamic version from cluster specification.

The function populatePGInstanceConfigurationMap is called from line 108 with access to ivoryCluster.Spec.PostgresVersion, but the function signature lacks a version parameter. Add postgresVersion int to the function signature and pass ivoryCluster.Spec.PostgresVersion from the call site. Then replace the hardcoded "18" at line 313 with strconv.Itoa(postgresVersion).

This aligns with the existing pattern used in internal/controller/ivorycluster/pgbackrest.go:679, where --pg-version-force is set dynamically to strconv.Itoa(ivoryCluster.Spec.PostgresVersion).

🤖 Prompt for AI Agents
In internal/pgbackrest/config.go around line 313, replace the hardcoded
stanza.Set("pg-version-force", "18") by making
populatePGInstanceConfigurationMap accept a postgresVersion int parameter (add
it to the function signature), use strconv.Itoa(postgresVersion) for the value,
and update the call site where populatePGInstanceConfigurationMap is invoked
(from where it was called at line 108) to pass
ivoryCluster.Spec.PostgresVersion; ensure strconv is imported if not already.

printf >&2 "%s" "${message}"; exit 1;
else
pgbackrest "${cmd}" --pg-version-force=17 --stanza="${stanza}"
pgbackrest "${cmd}" --pg-version-force=18 --stanza="${stanza}"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that hardcoded pg-version-force=18 doesn't break support for PostgreSQL versions 10-17.

The pgBackRest stanza creation script now forces PostgreSQL version 18 for all clusters. Since the operator supports PostgreSQL versions 10-18 (per CRD validation), forcing version 18 for clusters running older versions could potentially cause compatibility issues or unexpected behavior.

Run the following script to verify how pg-version-force is used across the codebase and whether it should be dynamic based on the cluster's actual version:


🏁 Script executed:

#!/bin/bash
# Search for pg-version-force usage and postgresVersion references

echo "=== Searching for pg-version-force usage ==="
rg -n "pg-version-force" --type go -C 3

echo -e "\n=== Searching for postgresVersion field usage in pgbackrest context ==="
rg -n "postgresVersion" internal/pgbackrest/ -C 3

echo -e "\n=== Checking if version is passed to pgbackrest functions ==="
ast-grep --pattern 'func $_(ctx context.Context, $$$) {
  $$$
  pgbackrest $$$
  $$$
}'

Length of output: 7396


I need to gather more context about how the cluster version is passed to the pgbackrest functions and understand the flow between the hardcoded values and the dynamic version handling.

Now let me search for function signatures in pgbackrest.go to understand how it's called and whether version info is available:

Let me search for the function that uses the pgbackrest.go script and config functions to understand the flow:


Based on my comprehensive analysis, I've identified a **critical breaking issue** with hardcoding the PostgreSQL version to 18:

**The hardcoded pg-version-force=18 breaks compatibility with PostgreSQL 10-17.**

The version reported by PostgreSQL via `server_version_num` must match the forced version. The evidence shows:

1. **Two locations hardcode version 18:**
   - `internal/pgbackrest/config.go:313` sets `pg-version-force = "18"`
   - `internal/pgbackrest/pgbackrest.go:73` uses `--pg-version-force=18` in the bash wrapper

2. **Dynamic version handling exists elsewhere:**
   - `internal/controller/ivorycluster/pgbackrest.go:679` correctly uses `--pg-version-force=` + `ivoryCluster.Spec.PostgresVersion` for backup jobs
   - Tests show dynamic version expectations (e.g., `--pg-version-force=13` for PostgreSQL 12)

3. **This violates pgBackRest's requirement:**
   pg-version-force value should be set to the same major version number as the server reports when using show server_version_num in PSQL. Forcing version 18 for clusters running PostgreSQL 10-17 will cause stanza operations to fail.

The review comment's concern is valid: this change breaks support for PostgreSQL 10-17 clusters by forcing all pgBackRest stanza operations to use version 18, which will cause version mismatch errors.

**Update `internal/pgbackrest/config.go:313` and `internal/pgbackrest/pgbackrest.go:73` to use dynamic PostgreSQL version instead of hardcoded 18. The version should be passed as a parameter from the cluster specification, matching the approach in `internal/controller/ivorycluster/pgbackrest.go:679`.**

---

🏁 Script executed:

```shell
#!/bin/bash

echo "=== Looking for functions that call pgbackrest.go functions ==="
rg -n "func.*Stanza" internal/pgbackrest/pgbackrest.go -A 5

echo -e "\n=== Searching for callers of CreateStanza or similar functions ==="
rg -n "CreateStanza\|NewStanzaCommand" --type go -B 2 -A 2

echo -e "\n=== Looking at config.go to see function signatures ==="
rg -n "func.*Config\|func.*Stanza" internal/pgbackrest/config.go -A 3 | head -50

Length of output: 378



---

🏁 Script executed:

```shell
#!/bin/bash

echo "=== Getting full StanzaCreateOrUpgrade function ==="
sed -n '53,120p' internal/pgbackrest/pgbackrest.go

echo -e "\n=== Searching for callers of StanzaCreateOrUpgrade ==="
rg -n "StanzaCreateOrUpgrade" --type go -B 3 -A 3

echo -e "\n=== Getting function signatures in config.go ==="
sed -n '1,50p' internal/pgbackrest/config.go | grep -n "func"
rg -n "^func" internal/pgbackrest/config.go -A 2

Length of output: 6875



---

🏁 Script executed:

```shell
#!/bin/bash

echo "=== Finding function containing call to StanzaCreateOrUpgrade at line 2604 ==="
sed -n '2550,2620p' internal/controller/ivorycluster/pgbackrest.go

echo -e "\n=== Looking for callers of this function in controller ==="
rg -n "reconcile.*Stanza\|func.*reconcile" internal/controller/ivorycluster/pgbackrest.go -B 2 -A 10 | head -80

Length of output: 3028



---

🏁 Script executed:

```shell
#!/bin/bash

echo "=== Finding function signature containing StanzaCreateOrUpgrade call ==="
rg -n "func.*{" internal/controller/ivorycluster/pgbackrest.go | awk -F: '{print $1}' | while read line; do
  next_line=$((line + 100))
  if sed -n "${line}p" internal/controller/ivorycluster/pgbackrest.go | grep -q "reconcile\|Stanza"; then
    if sed -n "${line},${next_line}p" internal/controller/ivorycluster/pgbackrest.go | grep -q "StanzaCreateOrUpgrade"; then
      echo "Function starting at line $line:"
      sed -n "${line},$((line+3))p" internal/controller/ivorycluster/pgbackrest.go
    fi
  fi
done

echo -e "\n=== Alternative: search around line 2604 ==="
sed -n '2450,2470p' internal/controller/ivorycluster/pgbackrest.go

echo -e "\n=== Look for reconcile function that calls stanza operations ==="
rg -n "func.*reconcile.*{" internal/controller/ivorycluster/pgbackrest.go -A 2

Length of output: 934



---

🏁 Script executed:

```shell
#!/bin/bash

echo "=== Finding function containing line 2604 ==="
grep -n "func" internal/controller/ivorycluster/pgbackrest.go | awk -F: '{if ($1 < 2604) print}' | tail -1

echo -e "\n=== Get that function signature ==="
line_num=$(grep -n "func" internal/controller/ivorycluster/pgbackrest.go | awk -F: '{if ($1 < 2604) print $1}' | tail -1)
sed -n "${line_num},$((line_num+2))p" internal/controller/ivorycluster/pgbackrest.go

echo -e "\n=== Check if ivoryCluster is available in that function ==="
sed -n "${line_num},2604p" internal/controller/ivorycluster/pgbackrest.go | grep -i "ivorycluster" | head -5

echo -e "\n=== Get the config hash creation to see if version could be passed ==="
sed -n '2450,2610p' internal/controller/ivorycluster/pgbackrest.go | head -100

Length of output: 4321


Pass PostgreSQL version dynamically instead of hardcoding version 18 in pgBackRest stanza configuration and script.

The hardcoded pg-version-force=18 breaks support for PostgreSQL 10-17 clusters. pgBackRest requires the forced version to match the actual cluster version reported via server_version_num. This causes stanza-create and stanza-upgrade operations to fail with version mismatch errors.

Required changes:

  • internal/pgbackrest/config.go:313: Use ivoryCluster.Spec.PostgresVersion instead of hardcoding "18"
  • internal/pgbackrest/pgbackrest.go:73: Pass PostgreSQL version as a parameter to the bash script instead of hardcoding --pg-version-force=18
  • internal/pgbackrest/pgbackrest.go:53 (StanzaCreateOrUpgrade): Add version parameter and pass it to the script

The reconcileStanzaCreate function at internal/controller/ivorycluster/pgbackrest.go:2567 already has access to ivoryCluster.Spec.PostgresVersion and must pass it through the call chain.

🤖 Prompt for AI Agents
In internal/pgbackrest/pgbackrest.go around line 73,
internal/pgbackrest/config.go at line 313, and internal/pgbackrest/pgbackrest.go
around line 53 (StanzaCreateOrUpgrade), replace the hardcoded
"--pg-version-force=18" with a dynamic value taken from
IvoryCluster.Spec.PostgresVersion: update config.go to reference
ivoryCluster.Spec.PostgresVersion instead of the string "18"; modify
StanzaCreateOrUpgrade to accept a postgresVersion parameter and pass that into
the script call; and change the bash invocation at line 73 to use the passed
postgresVersion value (e.g. --pg-version-force=<postgresVersion>) so
reconcileStanzaCreate (internal/controller/ivorycluster/pgbackrest.go:2567) can
forward ivoryCluster.Spec.PostgresVersion through the call chain.

Comment on lines +46 to +59
## IvorySQL Operator 5.0
- 数据库版本支持**ivorysql 5.0**
- 组件版本升级
- pgBackrest 2.56
- PgBouncer 1.23.0
- Patroni 4.0.7
- pgAdmin4 9.9
- pgExporter 0.17.0
- 插件版本升级
- PostGIS 3.5.4
- pgaudit 18.0
- pg_cron 1.6.7
- wal2json 2.6
- pgnodemx 1.7
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix markdown formatting: inconsistent indentation and hard tabs.

The new release notes section uses inconsistent indentation (4 spaces and tabs) instead of the standard 2-space indentation used in previous sections.

Apply this diff to fix the formatting:

 ## IvorySQL Operator 5.0
 - 数据库版本支持**ivorysql 5.0**
 - 组件版本升级
-    - pgBackrest 2.56
-    - PgBouncer 1.23.0
-    - Patroni 4.0.7
-    - pgAdmin4 9.9
-    - pgExporter 0.17.0
+  - pgBackrest 2.56
+  - PgBouncer 1.23.0
+  - Patroni 4.0.7
+  - pgAdmin4 9.9
+  - pgExporter 0.17.0
 - 插件版本升级
-	- PostGIS 3.5.4
-	- pgaudit 18.0
-	- pg_cron 1.6.7
-	- wal2json 2.6
-	- pgnodemx 1.7
+  - PostGIS 3.5.4
+  - pgaudit 18.0
+  - pg_cron 1.6.7
+  - wal2json 2.6
+  - pgnodemx 1.7
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## IvorySQL Operator 5.0
- 数据库版本支持**ivorysql 5.0**
- 组件版本升级
- pgBackrest 2.56
- PgBouncer 1.23.0
- Patroni 4.0.7
- pgAdmin4 9.9
- pgExporter 0.17.0
- 插件版本升级
- PostGIS 3.5.4
- pgaudit 18.0
- pg_cron 1.6.7
- wal2json 2.6
- pgnodemx 1.7
## IvorySQL Operator 5.0
- 数据库版本支持**ivorysql 5.0**
- 组件版本升级
- pgBackrest 2.56
- PgBouncer 1.23.0
- Patroni 4.0.7
- pgAdmin4 9.9
- pgExporter 0.17.0
- 插件版本升级
- PostGIS 3.5.4
- pgaudit 18.0
- pg_cron 1.6.7
- wal2json 2.6
- pgnodemx 1.7
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

49-49: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


50-50: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


51-51: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


52-52: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


53-53: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


55-55: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


55-55: Hard tabs
Column: 1

(MD010, no-hard-tabs)


56-56: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


56-56: Hard tabs
Column: 1

(MD010, no-hard-tabs)


57-57: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


57-57: Hard tabs
Column: 1

(MD010, no-hard-tabs)


58-58: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


58-58: Hard tabs
Column: 1

(MD010, no-hard-tabs)


59-59: Unordered list indentation
Expected: 2; Actual: 1

(MD007, ul-indent)


59-59: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In ivyo_release_notes.md around lines 46 to 59, the "IvorySQL Operator 5.0"
section uses inconsistent indentation (mix of 4 spaces and hard tabs) which
breaks the repository's 2-space markdown style; normalize all list indentation
to 2 spaces per level, replace hard tabs with two spaces, and ensure sub-list
items (components and plugins) are indented exactly two spaces under the main
bullet so spacing is consistent with the rest of the document.

Comment on lines +126 to 128
// +kubebuilder:validation:Maximum=18
// +operator-sdk:csv:customresourcedefinitions:type=spec,order=1
PostgresVersion int `json:"postgresVersion"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify PostgreSQL/IvorySQL version 18 availability and check for hardcoded version references.

The validation constraint update looks correct, but ensure that PostgreSQL/IvorySQL version 18 is officially released and that container images are available for this version. Additionally, verify there are no hardcoded version 17 references elsewhere in the codebase that could cause inconsistencies.

Please search the web to confirm version 18 availability:

Run the following script to check for hardcoded version references:


🏁 Script executed:

#!/bin/bash
# Description: Search for hardcoded references to version 17 that might need updating

echo "=== Searching for potential hardcoded version 17 references ==="
# Search for version 17 in Go files (excluding this file and test files initially)
rg -nP '\b(version|Version|IVORY|POSTGRES|PG).*17\b' --type=go -g '!*_test.go' -C2

echo -e "\n=== Checking environment variable patterns ==="
# Look for RELATED_IMAGE patterns with version 17
rg -nP 'RELATED_IMAGE.*17' --type=go -C2

echo -e "\n=== Checking for maximum/minimum version constraints ==="
# Find other validation Maximum annotations
rg -nP 'validation:(Maximum|Minimum)=17' --type=go -C2

Length of output: 169


🌐 Web query:

Is PostgreSQL 18 released and generally available?

💡 Result:

Yes. PostgreSQL 18 was released and made generally available on September 25, 2025. (postgresql.org)

Citations:


🌐 Web query:

Is IvorySQL 18 released and available?

💡 Result:

Short answer: No — there is no IvorySQL "18" release.

Details: IvorySQL's latest releases are in the 4.x series (most recently IvorySQL 4.4, released March 10, 2025). IvorySQL has not published a release numbered 18 or a release based on PostgreSQL 18. PostgreSQL 18 itself was released on September 25, 2025, but IvorySQL has not announced a PG‑18 based IvorySQL release as of the IvorySQL release notes. [1][2]

Sources:

  • IvorySQL 4.4 documentation / release notes (v4.4, Mar 10, 2025). [1]
  • PostgreSQL announcement noting PostgreSQL 18 release (Sept 25, 2025) / related IvorySQL posts. [2]

Revert PostgreSQL version 18 validation constraint—IvorySQL 18 is not released.

PostgreSQL 18 was released on September 25, 2025, but IvorySQL has not published a release numbered 18 or a release based on PostgreSQL 18. The latest IvorySQL release is version 4.4.

Updating the validation maximum to 18 allows users to attempt deploying a non-existent IvorySQL version, which will fail at runtime. This change must be reverted or held until IvorySQL 18 is officially released.

Additionally, verify that the same change was not made to pgupgrade_types.go (referenced in the AI summary).

🤖 Prompt for AI Agents
In pkg/apis/ivory-operator.ivorysql.org/v1beta1/ivorycluster_types.go around
lines 126-128, revert the validation change that set PostgresVersion maximum to
18; change the kubebuilder validation back to the previous supported maximum
(e.g., Maximum=17) or remove the 18 constraint until IvorySQL 18 is officially
released, and ensure the operator-sdk/csv tags remain consistent; also search
for and revert the same change in pgupgrade_types.go if present so both CRDs
enforce the same supported maximum.

@gaoxueyu gaoxueyu merged commit 1346995 into IvorySQL:master Nov 24, 2025
53 of 65 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Dec 15, 2025
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants