Add ignore_slots support to Patroni DCS configuration

- Add ignore_slots field to Patroni struct in CRD
- Add ignore_slots to patroniDCS struct for Spilo configuration
- Generate ignore_slots in SPILO_CONFIGURATION when specified
- Update CRD manifest to accept ignore_slots field
- Add unit test for ignore_slots configuration

This enables PostgreSQL 17 native slot synchronization support by allowing
users to configure Patroni to ignore specific replication slot types (e.g.,
logical slots) during failover operations.

Users can now configure ignore_slots in their PostgreSQL manifest:

  patroni:
    ignore_slots:
      - type: logical

This instructs Patroni to ignore logical replication slots during failover,
which is essential for PostgreSQL 17's native logical slot synchronization
feature where slots are automatically synced to standbys.
This commit is contained in:
Pavel Zaytsev 2025-12-23 16:18:09 -08:00
parent a06f8d796b
commit d0e215dee3
5 changed files with 36 additions and 0 deletions

View File

@ -327,6 +327,12 @@ spec:
properties:
failsafe_mode:
type: boolean
ignore_slots:
type: array
items:
type: object
additionalProperties:
type: string
initdb:
type: object
additionalProperties:

View File

@ -182,6 +182,7 @@ type Patroni struct {
SynchronousModeStrict bool `json:"synchronous_mode_strict,omitempty"`
SynchronousNodeCount uint32 `json:"synchronous_node_count,omitempty" defaults:"1"`
FailsafeMode *bool `json:"failsafe_mode,omitempty"`
IgnoreSlots []map[string]string `json:"ignore_slots,omitempty"`
}
// StandbyDescription contains remote primary config or s3/gs wal path

View File

@ -597,6 +597,19 @@ func (in *Patroni) DeepCopyInto(out *Patroni) {
*out = new(bool)
**out = **in
}
if in.IgnoreSlots != nil {
in, out := &in.IgnoreSlots, &out.IgnoreSlots
*out = make([]map[string]string, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
}
return
}

View File

@ -57,6 +57,7 @@ type patroniDCS struct {
PGBootstrapConfiguration map[string]interface{} `json:"postgresql,omitempty"`
Slots map[string]map[string]string `json:"slots,omitempty"`
FailsafeMode *bool `json:"failsafe_mode,omitempty"`
IgnoreSlots []map[string]string `json:"ignore_slots,omitempty"`
}
type pgBootstrap struct {
@ -441,6 +442,10 @@ PatroniInitDBParams:
config.Bootstrap.DCS.FailsafeMode = opConfig.EnablePatroniFailsafeMode
}
if patroni.IgnoreSlots != nil {
config.Bootstrap.DCS.IgnoreSlots = patroni.IgnoreSlots
}
config.PgLocalConfiguration = make(map[string]interface{})
// the newer and preferred way to specify the PG version is to use the `PGVERSION` env variable

View File

@ -135,6 +135,17 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"failsafe_mode":true}}}`,
},
{
subtest: "Patroni ignore_slots configured for PostgreSQL 17 slot sync",
pgParam: &acidv1.PostgresqlParam{PgVersion: "17"},
patroni: &acidv1.Patroni{
IgnoreSlots: []map[string]string{
{"type": "logical"},
},
},
opConfig: &config.Config{},
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/17/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"dcs":{"ignore_slots":[{"type":"logical"}]}}}`,
},
}
for _, tt := range tests {
cluster.OpConfig = *tt.opConfig