Skip to content

feat: add global database extensions flag to controller#375

Open
mahlunar wants to merge 5 commits into
masterfrom
dmat-64-add-global-database-extensions-flag-to-controller
Open

feat: add global database extensions flag to controller#375
mahlunar wants to merge 5 commits into
masterfrom
dmat-64-add-global-database-extensions-flag-to-controller

Conversation

@mahlunar
Copy link
Copy Markdown
Member

@mahlunar mahlunar commented May 27, 2026

Summary

Add --global-extensions flag to postgresql-controller that installs a consistent set of PostgreSQL extensions across all managed databases. Global extensions are merged with per-database extensions into a unique set before installation.

Why

Follows the pattern of --user-roles which applies global roles to all users. Allows operators to enforce a baseline set of extensions (e.g., pgcrypto, uuid-ossp, pg_stat_statements) without modifying every PostgreSQLDatabase CRD.

Closes DMAT-64


Note

Medium Risk
Reconciliation now installs additional extensions on all managed databases from operator config, which can change production DB state and fail if an extension is unavailable on the server.

Overview
Adds a --global-extensions controller flag (comma-separated names, parsed via GetGlobalExtensions() with trimming) so operators can enforce a baseline set of PostgreSQL extensions on every reconciled database, similar to --user-roles.

During PostgreSQLDatabase reconciliation, per-CRD spec.extensions are merged with the global list through mergeExtensions() (database entries first, deduplicated) before EnsurePostgreSQLDatabase runs. Startup wiring passes the parsed list from cmd/main.go into the reconciler, and config logging includes the raw flag value.

Coverage adds unit tests for flag parsing and merge behavior plus integration tests that assert extensions are actually installed on PostgreSQL. Unrelated cleanups use slices.Contains in the user controller and a for range loop style in a test helper.

Reviewed by Cursor Bugbot for commit 89ce176. Configure here.

Add --global-extensions flag that applies a consistent set of PostgreSQL
extensions across all managed databases. The flag accepts a comma-separated
list (e.g., --global-extensions=pgcrypto,uuid-ossp,pg_stat_statements).

Global extensions are merged with per-database extensions from
PostgreSQLDatabase.spec.extensions[] into a unique set before installation.
Database-specific extensions take precedence in the merge order.

Implementation:
- Add GlobalExtensions field to ControllerConfiguration with flag registration
- Add GetGlobalExtensions() method with whitespace trimming and empty filtering
- Pass global extensions to PostgreSQLDatabaseReconciler
- Add mergeExtensions() method using map-based deduplication
- Update startup logs to include global extensions

Tests:
- Flag parsing: empty, single, multiple, whitespace, trailing commas, empty elements, nil handling
- Merge logic: empty scenarios, global only, database only, both, duplicates, nil slices
- Integration: verify extensions actually install on PostgreSQL with exact match assertions

Also includes go fix improvements (slices.Contains, modern range loops).

Closes DMAT-64

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Comment thread internal/config/config.go
mahlunar and others added 2 commits May 27, 2026 09:07
- Return empty slice instead of nil in GetGlobalExtensions for empty input
- Fix SuperuserRoleName in extensions test to use iam_creator
- Quote extension and schema names to handle identifiers with hyphens (e.g., uuid-ossp)
- Remove unused fromApiExtensions function
- Fix tautological condition in status update switch statement

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@mahlunar mahlunar marked this pull request as ready for review May 27, 2026 07:24
@mahlunar mahlunar requested a review from a team as a code owner May 27, 2026 07:24
Comment thread internal/controller/postgresqldatabase_controller.go
{ExtensionName: "pgcrypto"},
},
expectedExtensions: []string{"pgcrypto", "uuid-ossp"},
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You could add a test where:

  • some or all extensions are already installed
  • an extension is installed that is not listed - I guess it should be removed? How do we keep track of that?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we see who installed the extension? We could have the assumption that all extensions installed by iam_creator are managed by the controller

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I will add the additional test but not add logic for removing in this PR

Comment thread pkg/postgres/extensions.go Outdated
Comment thread internal/config/config.go
result = append(result, trimmed)
}
}
return result
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we want to validate early that there are no clearly invalid extensions like some thing with spaces?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let's do that

Comment thread pkg/postgres/extensions.go
Co-authored-by: Tinus Mørch Abell <tmab@lunar.app>
@mahlunar
Copy link
Copy Markdown
Member Author

I think it is more dangerous to drop the extensions so let's document the behaviour so it is clear.

- Rename flag to --global-extensions-to-install to clarify that extensions
  are only installed, never removed
- Add validation for extension names to reject invalid characters and spaces
  early before attempting installation
- Add test case for already-installed extensions to verify reconciliation
  doesn't fail when extensions exist

Addresses feedback from @tmablunar on PR #375

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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