Skip to content

External database: unmanaged mode, custom Secret key, postgresql://#456

Open
jalet wants to merge 2 commits into
mattermost:masterfrom
jalet:feat/unmanaged-database
Open

External database: unmanaged mode, custom Secret key, postgresql://#456
jalet wants to merge 2 commits into
mattermost:masterfrom
jalet:feat/unmanaged-database

Conversation

@jalet
Copy link
Copy Markdown

@jalet jalet commented Apr 22, 2026

Summary

Two independent improvements to external-database support, aimed at consuming
pre-existing secrets produced by other operators (e.g. cloudnative-pg).

  • spec.database.unmanaged: true — operator skips all DB config; user supplies
    MM_SQLSETTINGS_* via spec.mattermostEnv.
  • spec.database.external.connectionStringKey — override the Secret key the
    operator reads the connection string from (default DB_CONNECTION_STRING).
    When set and no MM_SQLSETTINGS_DATASOURCE key is present in the Secret, the
    same key is reused as the datasource source, so a single uri entry is
    enough.
  • Accept postgresql:// scheme in DB_CONNECTION_CHECK_URL validation —
    pg_isready accepts both URI forms; GetTypeFromConnectionString already
    detected both via its postgres prefix check.

All three are opt-in; default behavior is unchanged.

Ticket Link

Fixes #437
Fixes #438

Release Note

Add two opt-in mechanisms for connecting Mattermost to pre-existing database secrets generated by other operators: spec.database.unmanaged skips all operator database configuration, and spec.database.external.connectionStringKey overrides the Secret key used to read the connection string. The postgresql:// URI scheme is now accepted alongside postgres:// in DB connection check URLs.

@mm-cloud-bot mm-cloud-bot added the kind/feature Categorizes issue or PR as related to a new feature. label Apr 22, 2026
@mm-cloud-bot
Copy link
Copy Markdown

@jalet: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Details

I understand the commands that are listed here

@mm-cloud-bot mm-cloud-bot added do-not-merge/release-note-label-needed release-note Denotes a PR that will be considered when it comes time to generate release notes. release-note-none Denotes a PR that doesn't merit a release note. and removed do-not-merge/release-note-label-needed release-note Denotes a PR that will be considered when it comes time to generate release notes. release-note-none Denotes a PR that doesn't merit a release note. labels Apr 22, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6143e96f-6bb6-42c2-87ba-a74a658f7958

📥 Commits

Reviewing files that changed from the base of the PR and between 129be17 and 3b7bee3.

📒 Files selected for processing (9)
  • apis/mattermost/v1beta1/db_util.go
  • apis/mattermost/v1beta1/db_util_test.go
  • apis/mattermost/v1beta1/mattermost_types.go
  • config/crd/bases/installation.mattermost.com_mattermosts.yaml
  • controllers/mattermost/mattermost/database.go
  • pkg/mattermost/database_external.go
  • pkg/mattermost/database_external_test.go
  • pkg/mattermost/mattermost_v1beta.go
  • pkg/mattermost/mattermost_v1beta_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/mattermost/database_external_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • controllers/mattermost/mattermost/database.go
  • apis/mattermost/v1beta1/db_util.go
  • apis/mattermost/v1beta1/mattermost_types.go
  • pkg/mattermost/mattermost_v1beta.go
  • config/crd/bases/installation.mattermost.com_mattermosts.yaml
  • pkg/mattermost/mattermost_v1beta_test.go
  • pkg/mattermost/database_external.go

📝 Walkthrough

Walkthrough

Adds Database.Unmanaged and ExternalDatabase.ConnectionStringKey, makes DB utility methods, controller, and deployment generator skip operator-managed DB behavior when unmanaged, extends external DB handling for configurable secret key and postgresql://, and adds tests across the stack.

Changes

Unmanaged DB + ExternalKey

Layer / File(s) Summary
API types and CRD
apis/mattermost/v1beta1/mattermost_types.go, config/crd/bases/installation.mattermost.com_mattermosts.yaml
Adds Database.Unmanaged and ExternalDatabase.ConnectionStringKey with docs/validation and CRD entries (default key DB_CONNECTION_STRING documented).
Database utils and tests
apis/mattermost/v1beta1/db_util.go, apis/mattermost/v1beta1/db_util_test.go
Adds (*Database).IsUnmanaged() and short-circuits SetDefaults, SetDefaultReplicasAndResources, and OverrideReplicasAndResourcesFromSize when unmanaged; tests verify behavior for nil/empty/unmanaged and that OperatorManaged is not populated.
External DB config and tests
pkg/mattermost/database_external.go, pkg/mattermost/database_external_test.go
Adds DefaultExternalDBConnectionStringKey, stores connectionStringKey on ExternalDBConfig, reads connection string from the configured secret key (and uses it as fallback for MM_SQLSETTINGS_DATASOURCE), accepts postgresql:// scheme; tests validate custom key usage, fallback, error messages, and scheme handling.
Controller & deployment generation + tests
controllers/mattermost/mattermost/database.go, pkg/mattermost/mattermost_v1beta.go, pkg/mattermost/mattermost_v1beta_test.go
checkDatabase returns (nil,nil) for unmanaged DB; GenerateDeploymentV1Beta skips operator DB env/init containers when unmanaged; test verifies no operator-injected MM_CONFIG and no init-check-database, while user SecretKeyRef remains.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly summarizes the three main changes: unmanaged database mode, custom Secret key configuration, and postgresql:// scheme support.
Description check ✅ Passed The description comprehensively explains all three opt-in improvements with specific implementation details, links to fixed issues, and a release note.
Linked Issues check ✅ Passed All coding requirements from issues #437 and #438 are met: custom Secret key field added with default fallback, unmanaged mode implemented with early returns, and postgresql:// scheme validation added.
Out of Scope Changes check ✅ Passed All changes directly implement the three requirements from linked issues #437 and #438; no unrelated modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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
Copy Markdown

@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 (1)
config/crd/bases/installation.mattermost.com_mattermosts.yaml (1)

104-121: ⚠️ Potential issue | 🟡 Minor

Update the Secret description to include custom keys.

Line 117 still says the Secret should contain DB_CONNECTION_STRING, but with connectionStringKey a Secret containing only uri is valid.

📝 Proposed documentation update
                       secret:
                         description: |-
                           Secret contains data necessary to connect to the external database.
                           The Kubernetes Secret should contain:
-                            - Key: DB_CONNECTION_STRING | Value: Full database connection string.
+                            - Key: DB_CONNECTION_STRING, or the key configured by connectionStringKey | Value: Full database connection string.
                           It can also contain optional fields, such as:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/crd/bases/installation.mattermost.com_mattermosts.yaml` around lines
104 - 121, Update the Secret description under the "secret" field to reflect
that the key for the connection string is configurable via connectionStringKey:
state that the default key is "DB_CONNECTION_STRING" but if connectionStringKey
is set the operator will use that key (for example "uri"), and that the operator
will also fall back to that key for MM_SQLSETTINGS_DATASOURCE when no
MM_SQLSETTINGS_DATASOURCE entry exists in the Secret; keep the existing optional
keys (MM_SQLSETTINGS_DATASOURCEREPLICAS, DB_CONNECTION_CHECK_URL) unchanged.
♻️ Duplicate comments (1)
apis/mattermost/v1alpha1/zz_generated.openapi.go (1)

20-338: ⚠️ Potential issue | 🟠 Major

Same unrelated path-format rewrite as v1beta1; please regenerate both together.

Every change in this file is the same class of rewrite as in apis/mattermost/v1beta1/zz_generated.openapi.go: schema map keys, factory function names, ref(...) targets, and Dependencies entries moved from github.com/mattermost/mattermost-operator/apis/mattermost/v1alpha1.* to ./apis/mattermost/v1alpha1.*, with the schema__apis_mattermost_v1alpha1_* double-underscore form indicating an empty module component.

v1alpha1 holds the deprecated ClusterInstallation API and is not part of this PR's feature scope (unmanaged DB / ConnectionStringKey / postgresql:// all live on v1beta1.Mattermost), so there is no functional reason for this file to have changed. See the detailed review on the v1beta1 file for the full concern about consumer impact and next-make generate thrash — the same remediation applies here: regenerate both files from an environment that produces the previous fully-qualified module-path keys, or make the rename explicit and intentional across both packages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apis/mattermost/v1alpha1/zz_generated.openapi.go` around lines 20 - 338,
Generated openapi keys and refs in zz_generated.openapi.go for package v1alpha1
were rewritten to relative paths (./apis/mattermost/v1alpha1.*) and
double-underscore schema function names (schema__apis_mattermost_v1alpha1_*),
matching the same unwanted change made in v1beta1; restore the original
fully-qualified module-path keys and factory names by regenerating the OpenAPI
files for both v1alpha1 and v1beta1 together from the correct generator
environment or reverting the changes: ensure functions like
schema__apis_mattermost_v1alpha1_ClusterInstallation (and its peers), the
ref(...) targets, and the Dependencies entries use the original
github.com/mattermost/mattermost-operator/apis/mattermost/v1alpha1.*
fully-qualified references instead of ./apis/... so both generated files are
consistent and prevent make generate churn.
🧹 Nitpick comments (1)
pkg/mattermost/mattermost_v1beta_test.go (1)

1125-1127: Exercise the unmanaged guard with a non-nil DB config.

Passing nil means this test would still pass if GenerateDeploymentV1Beta ignored Database.Unmanaged and only skipped DB injection because db == nil.

🧪 Proposed test strengthening
-	// Passing a nil DatabaseConfig mirrors checkDatabase returning nil for unmanaged.
-	deployment := GenerateDeploymentV1Beta(mattermost, nil, fileStore, "mm", "", "sa", "")
+	dbConfig := &ExternalDBConfig{
+		secretName:          "db-secret",
+		connectionStringKey: DefaultExternalDBConnectionStringKey,
+		hasDBCheckURL:       true,
+		dbType:              database.PostgreSQLDatabase,
+	}
+	deployment := GenerateDeploymentV1Beta(mattermost, dbConfig, fileStore, "mm", "", "sa", "")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/mattermost/mattermost_v1beta_test.go` around lines 1125 - 1127, The test
currently passes nil for the DB config so it can't verify the unmanaged guard;
instead construct and pass a non-nil database config with Unmanaged set true
(e.g., a DatabaseConfig/Database struct instance with Unmanaged: true) into
GenerateDeploymentV1Beta and keep the require.NotNil assertion — this ensures
GenerateDeploymentV1Beta actually checks Database.Unmanaged rather than simply
skipping DB injection due to a nil config.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apis/mattermost/v1beta1/mattermost_types.go`:
- Around line 361-368: Add kubebuilder CRD validation tags to the
ConnectionStringKey field to enforce allowed secret-key names and length:
annotate the ConnectionStringKey string with
+kubebuilder:validation:Pattern="^[A-Za-z0-9._-]+$" and
+kubebuilder:validation:MaxLength=253 (and keep +optional). Update the struct
field `ConnectionStringKey string `json:"connectionStringKey,omitempty"` in
mattermost_types.go to include these validation markers, then regenerate the
CRD/manifests so the schema includes the pattern and maxLength constraints.

---

Outside diff comments:
In `@config/crd/bases/installation.mattermost.com_mattermosts.yaml`:
- Around line 104-121: Update the Secret description under the "secret" field to
reflect that the key for the connection string is configurable via
connectionStringKey: state that the default key is "DB_CONNECTION_STRING" but if
connectionStringKey is set the operator will use that key (for example "uri"),
and that the operator will also fall back to that key for
MM_SQLSETTINGS_DATASOURCE when no MM_SQLSETTINGS_DATASOURCE entry exists in the
Secret; keep the existing optional keys (MM_SQLSETTINGS_DATASOURCEREPLICAS,
DB_CONNECTION_CHECK_URL) unchanged.

---

Duplicate comments:
In `@apis/mattermost/v1alpha1/zz_generated.openapi.go`:
- Around line 20-338: Generated openapi keys and refs in zz_generated.openapi.go
for package v1alpha1 were rewritten to relative paths
(./apis/mattermost/v1alpha1.*) and double-underscore schema function names
(schema__apis_mattermost_v1alpha1_*), matching the same unwanted change made in
v1beta1; restore the original fully-qualified module-path keys and factory names
by regenerating the OpenAPI files for both v1alpha1 and v1beta1 together from
the correct generator environment or reverting the changes: ensure functions
like schema__apis_mattermost_v1alpha1_ClusterInstallation (and its peers), the
ref(...) targets, and the Dependencies entries use the original
github.com/mattermost/mattermost-operator/apis/mattermost/v1alpha1.*
fully-qualified references instead of ./apis/... so both generated files are
consistent and prevent make generate churn.

---

Nitpick comments:
In `@pkg/mattermost/mattermost_v1beta_test.go`:
- Around line 1125-1127: The test currently passes nil for the DB config so it
can't verify the unmanaged guard; instead construct and pass a non-nil database
config with Unmanaged set true (e.g., a DatabaseConfig/Database struct instance
with Unmanaged: true) into GenerateDeploymentV1Beta and keep the require.NotNil
assertion — this ensures GenerateDeploymentV1Beta actually checks
Database.Unmanaged rather than simply skipping DB injection due to a nil config.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 327aae8a-47b6-4b76-a3d9-f24b8c8db087

📥 Commits

Reviewing files that changed from the base of the PR and between 8f8a8e1 and f79f0db.

📒 Files selected for processing (11)
  • apis/mattermost/v1alpha1/zz_generated.openapi.go
  • apis/mattermost/v1beta1/db_util.go
  • apis/mattermost/v1beta1/db_util_test.go
  • apis/mattermost/v1beta1/mattermost_types.go
  • apis/mattermost/v1beta1/zz_generated.openapi.go
  • config/crd/bases/installation.mattermost.com_mattermosts.yaml
  • controllers/mattermost/mattermost/database.go
  • pkg/mattermost/database_external.go
  • pkg/mattermost/database_external_test.go
  • pkg/mattermost/mattermost_v1beta.go
  • pkg/mattermost/mattermost_v1beta_test.go

Comment thread apis/mattermost/v1beta1/mattermost_types.go
@jalet jalet force-pushed the feat/unmanaged-database branch from f79f0db to 129be17 Compare April 23, 2026 06:46
@mattermost-build
Copy link
Copy Markdown
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

jalet added 2 commits May 12, 2026 11:52
Adds two independent mechanisms for connecting a Mattermost installation
to a pre-existing database secret (e.g. one generated by cloudnative-pg):

- spec.database.unmanaged: when true, the operator skips all database
  configuration. The user is responsible for supplying MM_SQLSETTINGS_*
  via spec.mattermostEnv, typically via valueFrom.secretKeyRef pointing
  at an external secret.

- spec.database.external.connectionStringKey: overrides the Secret key
  the operator reads the connection string from (default
  DB_CONNECTION_STRING). When set and no MM_SQLSETTINGS_DATASOURCE key
  is present in the Secret, the same key is reused as the
  MM_SQLSETTINGS_DATASOURCE source, so a single 'uri' entry is enough.

Fixes: mattermost#437
libpq-based clients (including pg_isready, which the operator uses for
the external-database readiness init container) accept both
"postgres://" and the officially-named "postgresql://" URI form.
cloudnative-pg and other postgres operators emit the postgresql://
variant, which was previously rejected by validateDBCheckURL.

Add postgresql as an allowed scheme for the postgres and unknown db
types. GetTypeFromConnectionString already detects both via its
"postgres" prefix check, and the connection string itself is passed
through unchanged via secretKeyRef, so no further changes are needed.

Fixes: mattermost#438
@jalet jalet force-pushed the feat/unmanaged-database branch from 129be17 to 3b7bee3 Compare May 12, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. Lifecycle/1:stale null release-note Denotes a PR that will be considered when it comes time to generate release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ability to use postgresql:// in addition to postgres:// ability to specify secret and data name within secret

3 participants