Skip to content

K8SPG-650: add .spec.proxy.pgBouncer.usersSecret#1659

Open
pooknull wants to merge 2 commits into
mainfrom
K8SPG-650
Open

K8SPG-650: add .spec.proxy.pgBouncer.usersSecret#1659
pooknull wants to merge 2 commits into
mainfrom
K8SPG-650

Conversation

@pooknull

@pooknull pooknull commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

https://perconadev.atlassian.net/browse/K8SPG-650

DESCRIPTION

This PR adds .spec.proxy.pgBouncer.usersSecret to allow adding custom users to pgbouncer.

Example of the secret:

apiVersion: v1
kind: Secret
metadata:
  name: pgbouncer-users
type: Opaque
stringData:
  stats_user: stats-password
  monitoring_user: monitoring-password

The operator reads each key/value from the secret and appends it to the pgbouncer-users.txt file. Each secret key is used as a username, and each secret value is used as password

CHECKLIST

Jira

  • Is the Jira ticket created and referenced properly?
  • Does the Jira ticket have the proper statuses for documentation (Needs Doc) and QA (Needs QA)?
  • Does the Jira ticket link to the proper milestone (Fix Version field)?

Tests

  • Is an E2E test/test case added for the new feature/change?
  • Are unit tests added where appropriate?

Config/Logging/Testability

  • Are all needed new/changed options added to default YAML files?
  • Are all needed new/changed options added to the Helm Chart?
  • Did we add proper logging messages for operator actions?
  • Did we ensure compatibility with the previous version or cluster upgrade process?
  • Does the change support oldest and newest supported PG version?
  • Does the change support oldest and newest supported Kubernetes version?

Copilot AI left a comment

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.

Pull request overview

Adds support for referencing a Kubernetes Secret at .spec.proxy.pgBouncer.usersSecret so the operator can append additional PgBouncer users into pgbouncer-users.txt, and wires up field indexes/watches so changes to that Secret trigger reconciles.

Changes:

  • Extend PgBouncer specs (upstream + Percona API) with usersSecret and propagate it through conversion/deepcopy generation.
  • Update PgBouncer secret reconciliation to merge extra users into the generated auth file, plus add Secret watches/indexers for reconcile triggers.
  • Add unit/E2E coverage validating the users are appended into pgbouncer-users.txt.

Reviewed changes

Copilot reviewed 20 out of 23 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/apis/upstream.pgv2.percona.com/v1beta1/zz_generated.deepcopy.go Deepcopy updates for new UsersSecret field.
pkg/apis/upstream.pgv2.percona.com/v1beta1/postgrescluster_types.go Adds PgBouncer usersSecret field index helper + indexer func.
pkg/apis/upstream.pgv2.percona.com/v1beta1/pgbouncer_types.go Adds usersSecret to upstream PgBouncer pod spec.
pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go Deepcopy updates for new UsersSecret field.
pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go Adds usersSecret to Percona PgBouncer spec, converts to upstream, and adds index helper + indexer func.
percona/controller/pgcluster/controller.go Watches Secret changes for Percona clusters using usersSecret.
internal/pgbouncer/reconcile.go Passes usersSecret into auth file generation during Secret reconcile.
internal/pgbouncer/reconcile_test.go Verifies reconcile writes the extra user into pgbouncer-users.txt.
internal/pgbouncer/config.go Extends auth file generation to append users from a Secret (sorted).
internal/pgbouncer/config_test.go Adds unit test for multi-user auth file generation and escaping.
internal/controller/postgrescluster/watches.go Adds watch mapping Secrets referenced by usersSecret to PostgresCluster reconcile requests.
internal/controller/postgrescluster/pgbouncer.go Fetches the referenced usersSecret and passes it into PgBouncer Secret reconcile.
internal/controller/postgrescluster/controller.go Registers field index and watches Secrets referenced by usersSecret.
e2e-tests/tests/users/23-assert.yaml E2E assert verifying usersSecret is set and auth file contains appended user.
e2e-tests/tests/users/23-add-pgbouncer-user.yaml E2E step that creates the users Secret and patches the cluster to reference it.
deploy/cw-bundle.yaml CRD bundle schema update for usersSecret.
deploy/crd.yaml CRD schema update for usersSecret.
deploy/cr.yaml Example manifest updates documenting usersSecret.
deploy/bundle.yaml CRD bundle schema update for usersSecret.
config/crd/bases/upstream.pgv2.percona.com_postgresclusters.yaml Upstream CRD base schema update for usersSecret.
config/crd/bases/pgv2.percona.com_perconapgclusters.yaml Percona CRD base schema update for usersSecret.
cmd/postgres-operator/main.go Registers Percona cluster field indexer for usersSecret.
build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml Generated Percona CRD schema update for usersSecret.
Files not reviewed (2)
  • pkg/apis/pgv2.percona.com/v2/zz_generated.deepcopy.go: Generated file
  • pkg/apis/upstream.pgv2.percona.com/v1beta1/zz_generated.deepcopy.go: Generated file

Comment on lines +80 to +85
for name, password := range userSecret.Data {
if strings.ContainsAny(string(password), "\r\n") {
return nil, errors.Errorf("pgbouncer user %q in Secret %q contains a newline", name, userSecret.Name)
}
users[name] = string(password)
}
Comment on lines +268 to +274
var userSecret *corev1.Secret
if ref := cluster.Spec.Proxy.PGBouncer.UsersSecret; ref != nil {
userSecret = &corev1.Secret{}
if err := r.Client.Get(ctx, client.ObjectKey{Namespace: cluster.Namespace, Name: ref.Name}, userSecret); err != nil {
return nil, errors.Wrapf(err, "get PgBouncer users Secret %q", ref.Name)
}
}
Comment on lines +214 to +218
if cluster.Spec.Proxy.PGBouncer.UsersSecret == nil {
return nil
}
return []string{cluster.Spec.Proxy.PGBouncer.UsersSecret.Name}
}
Comment on lines +1366 to +1373
func (cr *PerconaPGCluster) PGBouncerUserSecrets() []string {
if cr.Spec.Proxy == nil || cr.Spec.Proxy.PGBouncer == nil ||
cr.Spec.Proxy.PGBouncer.UsersSecret == nil {
return nil
}

return []string{cr.Spec.Proxy.PGBouncer.UsersSecret.Name}
}
@JNKPercona

Copy link
Copy Markdown
Collaborator
Test Name Result Time
backup-enable-disable passed 00:13:06
builtin-extensions passed 00:06:12
cert-manager-tls passed 00:09:19
custom-envs passed 00:19:06
custom-tls passed 00:05:58
database-init-sql passed 00:02:35
demand-backup passed 00:21:59
demand-backup-offline-snapshot passed 00:13:31
dynamic-configuration passed 00:03:28
finalizers passed 00:03:39
init-deploy passed 00:03:24
huge-pages passed 00:02:58
major-upgrade-14-to-15 passed 00:11:05
major-upgrade-15-to-16 passed 00:11:33
major-upgrade-16-to-17 passed 00:10:33
major-upgrade-17-to-18 passed 00:09:05
ldap passed 00:04:05
ldap-tls passed 00:05:39
monitoring passed 00:08:12
monitoring-pmm3 passed 00:09:26
one-pod passed 00:06:07
operator-self-healing passed 00:10:10
pitr passed 00:12:12
scaling passed 00:05:23
scheduled-backup passed 00:30:04
self-healing passed 00:08:22
sidecars passed 00:03:00
standby-pgbackrest passed 00:20:02
standby-streaming passed 00:13:00
start-from-backup passed 00:11:21
tablespaces passed 00:07:33
telemetry-transfer passed 00:04:25
upgrade-consistency passed 00:06:26
upgrade-minor passed 00:07:39
users passed 00:05:23
Summary Value
Tests Run 35/35
Job Duration 01:50:52
Total Test Time 05:26:17

commit: cd3d6e2
image: perconalab/percona-postgresql-operator:PR-1659-cd3d6e2af

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.

3 participants