cloudnative-pg / cloudnative-pg/charts
Add declarative `Publication` and `Subscription` support to the cluster chart
- Dominant language
- Go Template
- Stars
- 621
- Forks
- 265
- Avg merge
- 7d 12h
- Merged PRs (30d)
- 7
Description
## Summary
The CNPG operator supports declarative management of [`Publication`](https://cloudnative-pg.io/documentation/current/declarative_publication_management/) and [`Subscription`](https://cloudnative-pg.io/documentation/current/declarative_subscription_management/) CRDs, but the `cluster` Helm chart currently has no way to render them. Users wanting native logical replication (e.g. for major-version upgrades or cross-cluster migration) have to drop down to raw manifests alongside the chart.
I'd like to propose adding first-class support to the `cluster` chart and am volunteering to do the work, opening this issue first per CONTRIBUTING.md to align on shape before submitting a PR.
## Prior discussion
- #732: user asked for exactly this; closed stale without resolution.
- #692: broader chart-coverage proposal that lists publications/subscriptions among the gaps; closed stale.
- #831: open bug. Standalone mode strips `externalClusters`, which blocks the subscriber side of any cross-cluster logical replication.
- #832: open PR fixing #831 by allowing a raw `cluster.externalClusters` to render in standalone mode.
I have no maintainer signal that any of the above is being actively pursued; happy to coordinate if so.
## Proposal
Add three things to the `cluster` chart:
1. **`publications: []`**: list rendering one `postgresql.cnpg.io/v1` `Publication` per entry. Fields: `name`, `dbname`, `target` (`allTables` xor `objects`), optional `parameters`, `publicationReclaimPolicy`.
2. **`subscriptions: []`**: list rendering one `Subscription` per entry. Fields: `name`, `dbname`, `publicationName`, `externalClusterName`, optional `parameters`, `subscriptionReclaimPolicy`.
3. **A way to declare the source cluster connection** for `Subscription.externalClusterName`. See open question below.
Plus: documentation page, two examples (publisher / subscriber), and a chainsaw test that stands up two clusters, replicates rows, and asserts row counts on the subscriber.
## Open question: connection-config shape
There are two reasonable places for the externalCluster connection to live:
**Option A: typed `logicalReplication.externalClusters`** (what I prototyped):
```yaml
logicalReplication:
externalClusters:
- name: source-cluster
host: source-rw.default.svc
port: 5432
username: app
database: app
sslMode: verify-full
passwordSecret: { create: false, name: source-app, key: password }
sslRootCertSecret: { name: ..., key: ... }
```
Pros: helm-validated schema, optional secret creation (`create: true` with `value:`), familiar shape (mirrors `recovery.pg_basebackup.source`).
Cons: duplicates the CNPG `externalClusters` schema.
**Option B: reuse `cluster.externalClusters` from #832**
Once #832 lands, users put the full upstream `externalClusters` entry directly into `cluster.externalClusters` and reference it by name from `subscriptions[].externalClusterName`.
Pros: single source of truth, no schema duplication, automatically inherits any new CRD fields.
Cons: no helm-side validation, no convenience secret creation; users hand-write the full CNPG shape.
I have a working implementation of Option A but am happy to rework to Option B (or a hybrid where Option A renders into the same `externalClusters` list #832 introduces). What's your preference, @itay-grudev?
## What I have ready
A working branch with:
- the three template files,
- `values.schema.json` updates,
- `helm-docs`-regenerated README,
- examples for publisher and subscriber,
- three chainsaw tests (`logical-replication`, `logical-replication-objects`, `logical-replication-schema`) covering `allTables`, specific objects, and schema-scoped publications, with `test`-style assertions on row counts and replicated objects.
I'll rebase onto current `main`, sign off commits per DCO, and open the PR as `dev/` once the shape question is resolved.
## Out of scope (for this issue)
- The standalone-mode `externalClusters` rendering itself, tracked in #831 / #832.
- Replica clusters / `replica.origin` changes, separate concern.
- Plugin-based logical replication (if/when CNPG adds it).
Contributor guide
Assessment
This issue has not been assessed yet.