enable operator support for pg15 and drop support for 9.5 and 9.6 (#2140)

* enable operator support for pg15 and drop support for 9.5 and 9.6
* not offer 15 in UI before spilo-15 is available
This commit is contained in:
Felix Kunde 2022-12-15 12:17:27 +01:00 committed by GitHub
parent 81e17e4af1
commit 3e148ea57e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 54 additions and 59 deletions

View File

@ -29,13 +29,13 @@ pipelines with no access to Kubernetes API directly, promoting infrastructure as
### PostgreSQL features ### PostgreSQL features
* Supports PostgreSQL 14, starting from 9.6+ * Supports PostgreSQL 14, starting from 10+
* Streaming replication cluster via Patroni * Streaming replication cluster via Patroni
* Point-In-Time-Recovery with * Point-In-Time-Recovery with
[pg_basebackup](https://www.postgresql.org/docs/11/app-pgbasebackup.html) / [pg_basebackup](https://www.postgresql.org/docs/11/app-pgbasebackup.html) /
[WAL-E](https://github.com/wal-e/wal-e) via [Spilo](https://github.com/zalando/spilo) [WAL-E](https://github.com/wal-e/wal-e) via [Spilo](https://github.com/zalando/spilo)
* Preload libraries: [bg_mon](https://github.com/CyberDem0n/bg_mon), * Preload libraries: [bg_mon](https://github.com/CyberDem0n/bg_mon),
[pg_stat_statements](https://www.postgresql.org/docs/14/pgstatstatements.html), [pg_stat_statements](https://www.postgresql.org/docs/15/pgstatstatements.html),
[pgextwlist](https://github.com/dimitri/pgextwlist), [pgextwlist](https://github.com/dimitri/pgextwlist),
[pg_auth_mon](https://github.com/RafiaSabih/pg_auth_mon) [pg_auth_mon](https://github.com/RafiaSabih/pg_auth_mon)
* Incl. popular Postgres extensions such as * Incl. popular Postgres extensions such as

View File

@ -167,7 +167,7 @@ spec:
type: string type: string
minimal_major_version: minimal_major_version:
type: string type: string
default: "9.6" default: "11"
target_major_version: target_major_version:
type: string type: string
default: "14" default: "14"

View File

@ -367,13 +367,12 @@ spec:
version: version:
type: string type: string
enum: enum:
- "9.5"
- "9.6"
- "10" - "10"
- "11" - "11"
- "12" - "12"
- "13" - "13"
- "14" - "14"
- "15"
parameters: parameters:
type: object type: object
additionalProperties: additionalProperties:

View File

@ -89,7 +89,7 @@ configMajorVersionUpgrade:
# - acid # - acid
# minimal Postgres major version that will not automatically be upgraded # minimal Postgres major version that will not automatically be upgraded
minimal_major_version: "9.6" minimal_major_version: "11"
# target Postgres major version when upgrading clusters automatically # target Postgres major version when upgrading clusters automatically
target_major_version: "14" target_major_version: "14"

View File

@ -23,13 +23,12 @@ RUN apt-get update \
&& curl --silent https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && curl --silent https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt-get update \ && apt-get update \
&& apt-get install --no-install-recommends -y \ && apt-get install --no-install-recommends -y \
postgresql-client-15 \
postgresql-client-14 \ postgresql-client-14 \
postgresql-client-13 \ postgresql-client-13 \
postgresql-client-12 \ postgresql-client-12 \
postgresql-client-11 \ postgresql-client-11 \
postgresql-client-10 \ postgresql-client-10 \
postgresql-client-9.6 \
postgresql-client-9.5 \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*

View File

@ -1111,7 +1111,7 @@ aws_or_gcp:
If cluster members have to be (re)initialized restoring physical backups If cluster members have to be (re)initialized restoring physical backups
happens automatically either from the backup location or by running happens automatically either from the backup location or by running
[pg_basebackup](https://www.postgresql.org/docs/13/app-pgbasebackup.html) [pg_basebackup](https://www.postgresql.org/docs/15/app-pgbasebackup.html)
on one of the other running instances (preferably replicas if they do not lag on one of the other running instances (preferably replicas if they do not lag
behind). You can test restoring backups by [cloning](user.md#how-to-clone-an-existing-postgresql-cluster) behind). You can test restoring backups by [cloning](user.md#how-to-clone-an-existing-postgresql-cluster)
clusters. clusters.

View File

@ -558,7 +558,7 @@ Those parameters are grouped under the `tls` top-level key.
## Change data capture streams ## Change data capture streams
This sections enables change data capture (CDC) streams via Postgres' This sections enables change data capture (CDC) streams via Postgres'
[logical decoding](https://www.postgresql.org/docs/14/logicaldecoding.html) [logical decoding](https://www.postgresql.org/docs/15/logicaldecoding.html)
feature and `pgoutput` plugin. While the Postgres operator takes responsibility feature and `pgoutput` plugin. While the Postgres operator takes responsibility
for providing the setup to publish change events, it relies on external tools for providing the setup to publish change events, it relies on external tools
to consume them. At Zalando, we are using a workflow based on to consume them. At Zalando, we are using a workflow based on
@ -590,7 +590,7 @@ can have the following properties:
and `payloadColumn`). The CDC operator is following the [outbox pattern](https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/). and `payloadColumn`). The CDC operator is following the [outbox pattern](https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/).
The application is responsible for putting events into a (JSON/B or VARCHAR) The application is responsible for putting events into a (JSON/B or VARCHAR)
payload column of the outbox table in the structure of the specified target payload column of the outbox table in the structure of the specified target
event type. The operator will create a [PUBLICATION](https://www.postgresql.org/docs/14/logical-replication-publication.html) event type. The operator will create a [PUBLICATION](https://www.postgresql.org/docs/15/logical-replication-publication.html)
in Postgres for all tables specified for one `database` and `applicationId`. in Postgres for all tables specified for one `database` and `applicationId`.
The CDC operator will consume from it shortly after transactions are The CDC operator will consume from it shortly after transactions are
committed to the outbox table. The `idColumn` will be used in telemetry for committed to the outbox table. The `idColumn` will be used in telemetry for

View File

@ -246,7 +246,7 @@ CRD-configuration, they are grouped under the `major_version_upgrade` key.
* **minimal_major_version** * **minimal_major_version**
The minimal Postgres major version that will not automatically be upgraded The minimal Postgres major version that will not automatically be upgraded
when `major_version_upgrade_mode` is set to `"full"`. The default is `"9.6"`. when `major_version_upgrade_mode` is set to `"full"`. The default is `"11"`.
* **target_major_version** * **target_major_version**
The target Postgres major version when upgrading clusters automatically The target Postgres major version when upgrading clusters automatically

View File

@ -517,7 +517,7 @@ Postgres Operator will create the following NOLOGIN roles:
The `<dbname>_owner` role is the database owner and should be used when creating The `<dbname>_owner` role is the database owner and should be used when creating
new database objects. All members of the `admin` role, e.g. teams API roles, can new database objects. All members of the `admin` role, e.g. teams API roles, can
become the owner with the `SET ROLE` command. [Default privileges](https://www.postgresql.org/docs/12/sql-alterdefaultprivileges.html) become the owner with the `SET ROLE` command. [Default privileges](https://www.postgresql.org/docs/15/sql-alterdefaultprivileges.html)
are configured for the owner role so that the `<dbname>_reader` role are configured for the owner role so that the `<dbname>_reader` role
automatically gets read-access (SELECT) to new tables and sequences and the automatically gets read-access (SELECT) to new tables and sequences and the
`<dbname>_writer` receives write-access (INSERT, UPDATE, DELETE on tables, `<dbname>_writer` receives write-access (INSERT, UPDATE, DELETE on tables,
@ -592,7 +592,7 @@ spec:
### Schema `search_path` for default roles ### Schema `search_path` for default roles
The schema [`search_path`](https://www.postgresql.org/docs/13/ddl-schemas.html#DDL-SCHEMAS-PATH) The schema [`search_path`](https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PATH)
for each role will include the role name and the schemas, this role should have for each role will include the role name and the schemas, this role should have
access to. So `foo_bar_writer` does not have to schema-qualify tables from access to. So `foo_bar_writer` does not have to schema-qualify tables from
schemas `foo_bar_writer, bar`, while `foo_writer` can look up `foo_writer` and schemas `foo_bar_writer, bar`, while `foo_writer` can look up `foo_writer` and
@ -812,7 +812,7 @@ spec:
### Clone directly ### Clone directly
Another way to get a fresh copy of your source DB cluster is via Another way to get a fresh copy of your source DB cluster is via
[pg_basebackup](https://www.postgresql.org/docs/13/app-pgbasebackup.html). To [pg_basebackup](https://www.postgresql.org/docs/15/app-pgbasebackup.html). To
use this feature simply leave out the timestamp field from the clone section. use this feature simply leave out the timestamp field from the clone section.
The operator will connect to the service of the source cluster by name. If the The operator will connect to the service of the source cluster by name. If the
cluster is called test, then the connection string will look like host=test cluster is called test, then the connection string will look like host=test

View File

@ -97,7 +97,7 @@ data:
# max_memory_request: 4Gi # max_memory_request: 4Gi
# min_cpu_limit: 250m # min_cpu_limit: 250m
# min_memory_limit: 250Mi # min_memory_limit: 250Mi
# minimal_major_version: "9.6" # minimal_major_version: "11"
# node_readiness_label: "status:ready" # node_readiness_label: "status:ready"
# node_readiness_label_merge: "OR" # node_readiness_label_merge: "OR"
# oauth_token_secret_name: postgresql-operator # oauth_token_secret_name: postgresql-operator

View File

@ -165,7 +165,7 @@ spec:
type: string type: string
minimal_major_version: minimal_major_version:
type: string type: string
default: "9.6" default: "11"
target_major_version: target_major_version:
type: string type: string
default: "14" default: "14"

View File

@ -39,7 +39,7 @@ configuration:
major_version_upgrade_mode: "off" major_version_upgrade_mode: "off"
# major_version_upgrade_team_allow_list: # major_version_upgrade_team_allow_list:
# - acid # - acid
minimal_major_version: "9.6" minimal_major_version: "11"
target_major_version: "14" target_major_version: "14"
kubernetes: kubernetes:
# additional_pod_capabilities: # additional_pod_capabilities:

View File

@ -365,13 +365,12 @@ spec:
version: version:
type: string type: string
enum: enum:
- "9.5"
- "9.6"
- "10" - "10"
- "11" - "11"
- "12" - "12"
- "13" - "13"
- "14" - "14"
- "15"
parameters: parameters:
type: object type: object
additionalProperties: additionalProperties:

View File

@ -580,12 +580,6 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{
"version": { "version": {
Type: "string", Type: "string",
Enum: []apiextv1.JSON{ Enum: []apiextv1.JSON{
{
Raw: []byte(`"9.5"`),
},
{
Raw: []byte(`"9.6"`),
},
{ {
Raw: []byte(`"10"`), Raw: []byte(`"10"`),
}, },
@ -601,6 +595,9 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{
{ {
Raw: []byte(`"14"`), Raw: []byte(`"14"`),
}, },
{
Raw: []byte(`"15"`),
},
}, },
}, },
"parameters": { "parameters": {

View File

@ -49,7 +49,7 @@ type PostgresUsersConfiguration struct {
type MajorVersionUpgradeConfiguration struct { type MajorVersionUpgradeConfiguration struct {
MajorVersionUpgradeMode string `json:"major_version_upgrade_mode" default:"off"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade MajorVersionUpgradeMode string `json:"major_version_upgrade_mode" default:"off"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade
MajorVersionUpgradeTeamAllowList []string `json:"major_version_upgrade_team_allow_list,omitempty"` MajorVersionUpgradeTeamAllowList []string `json:"major_version_upgrade_team_allow_list,omitempty"`
MinimalMajorVersion string `json:"minimal_major_version" default:"9.6"` MinimalMajorVersion string `json:"minimal_major_version" default:"11"`
TargetMajorVersion string `json:"target_major_version" default:"14"` TargetMajorVersion string `json:"target_major_version" default:"14"`
} }

View File

@ -213,7 +213,7 @@ var unmarshalCluster = []struct {
"127.0.0.1/32" "127.0.0.1/32"
], ],
"postgresql": { "postgresql": {
"version": "9.6", "version": "15",
"parameters": { "parameters": {
"shared_buffers": "32MB", "shared_buffers": "32MB",
"max_connections": "10", "max_connections": "10",
@ -273,7 +273,7 @@ var unmarshalCluster = []struct {
}, },
Spec: PostgresSpec{ Spec: PostgresSpec{
PostgresqlParam: PostgresqlParam{ PostgresqlParam: PostgresqlParam{
PgVersion: "9.6", PgVersion: "15",
Parameters: map[string]string{ Parameters: map[string]string{
"shared_buffers": "32MB", "shared_buffers": "32MB",
"max_connections": "10", "max_connections": "10",
@ -333,7 +333,7 @@ var unmarshalCluster = []struct {
}, },
Error: "", Error: "",
}, },
marshal: []byte(`{"kind":"Postgresql","apiVersion":"acid.zalan.do/v1","metadata":{"name":"acid-testcluster1","creationTimestamp":null},"spec":{"postgresql":{"version":"9.6","parameters":{"log_statement":"all","max_connections":"10","shared_buffers":"32MB"}},"pod_priority_class_name":"spilo-pod-priority","volume":{"size":"5Gi","storageClass":"SSD", "subPath": "subdir"},"enableShmVolume":false,"patroni":{"initdb":{"data-checksums":"true","encoding":"UTF8","locale":"en_US.UTF-8"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"],"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}},"resources":{"requests":{"cpu":"10m","memory":"50Mi"},"limits":{"cpu":"300m","memory":"3000Mi"}},"teamId":"acid","allowedSourceRanges":["127.0.0.1/32"],"numberOfInstances":2,"users":{"zalando":["superuser","createdb"]},"maintenanceWindows":["Mon:01:00-06:00","Sat:00:00-04:00","05:00-05:15"],"clone":{"cluster":"acid-batman"}},"status":{"PostgresClusterStatus":""}}`), marshal: []byte(`{"kind":"Postgresql","apiVersion":"acid.zalan.do/v1","metadata":{"name":"acid-testcluster1","creationTimestamp":null},"spec":{"postgresql":{"version":"15","parameters":{"log_statement":"all","max_connections":"10","shared_buffers":"32MB"}},"pod_priority_class_name":"spilo-pod-priority","volume":{"size":"5Gi","storageClass":"SSD", "subPath": "subdir"},"enableShmVolume":false,"patroni":{"initdb":{"data-checksums":"true","encoding":"UTF8","locale":"en_US.UTF-8"},"pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"],"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}},"resources":{"requests":{"cpu":"10m","memory":"50Mi"},"limits":{"cpu":"300m","memory":"3000Mi"}},"teamId":"acid","allowedSourceRanges":["127.0.0.1/32"],"numberOfInstances":2,"users":{"zalando":["superuser","createdb"]},"maintenanceWindows":["Mon:01:00-06:00","Sat:00:00-04:00","05:00-05:15"],"clone":{"cluster":"acid-batman"}},"status":{"PostgresClusterStatus":""}}`),
err: nil}, err: nil},
{ {
about: "example with clone", about: "example with clone",
@ -398,7 +398,7 @@ var postgresqlList = []struct {
out PostgresqlList out PostgresqlList
err error err error
}{ }{
{"expect success", []byte(`{"apiVersion":"v1","items":[{"apiVersion":"acid.zalan.do/v1","kind":"Postgresql","metadata":{"labels":{"team":"acid"},"name":"acid-testcluster42","namespace":"default","resourceVersion":"30446957","selfLink":"/apis/acid.zalan.do/v1/namespaces/default/postgresqls/acid-testcluster42","uid":"857cd208-33dc-11e7-b20a-0699041e4b03"},"spec":{"allowedSourceRanges":["185.85.220.0/22"],"numberOfInstances":1,"postgresql":{"version":"9.6"},"teamId":"acid","volume":{"size":"10Gi"}},"status":{"PostgresClusterStatus":"Running"}}],"kind":"List","metadata":{},"resourceVersion":"","selfLink":""}`), {"expect success", []byte(`{"apiVersion":"v1","items":[{"apiVersion":"acid.zalan.do/v1","kind":"Postgresql","metadata":{"labels":{"team":"acid"},"name":"acid-testcluster42","namespace":"default","resourceVersion":"30446957","selfLink":"/apis/acid.zalan.do/v1/namespaces/default/postgresqls/acid-testcluster42","uid":"857cd208-33dc-11e7-b20a-0699041e4b03"},"spec":{"allowedSourceRanges":["185.85.220.0/22"],"numberOfInstances":1,"postgresql":{"version":"15"},"teamId":"acid","volume":{"size":"10Gi"}},"status":{"PostgresClusterStatus":"Running"}}],"kind":"List","metadata":{},"resourceVersion":"","selfLink":""}`),
PostgresqlList{ PostgresqlList{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "List", Kind: "List",
@ -419,7 +419,7 @@ var postgresqlList = []struct {
}, },
Spec: PostgresSpec{ Spec: PostgresSpec{
ClusterName: "testcluster42", ClusterName: "testcluster42",
PostgresqlParam: PostgresqlParam{PgVersion: "9.6"}, PostgresqlParam: PostgresqlParam{PgVersion: "15"},
Volume: Volume{Size: "10Gi"}, Volume: Volume{Size: "10Gi"},
TeamID: "acid", TeamID: "acid",
AllowedSourceRanges: []string{"185.85.220.0/22"}, AllowedSourceRanges: []string{"185.85.220.0/22"},

View File

@ -74,18 +74,18 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
}{ }{
{ {
subtest: "Patroni default configuration", subtest: "Patroni default configuration",
pgParam: &acidv1.PostgresqlParam{PgVersion: "9.6"}, pgParam: &acidv1.PostgresqlParam{PgVersion: "15"},
patroni: &acidv1.Patroni{}, patroni: &acidv1.Patroni{},
opConfig: &config.Config{ opConfig: &config.Config{
Auth: config.Auth{ Auth: config.Auth{
PamRoleName: "zalandos", PamRoleName: "zalandos",
}, },
}, },
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/9.6/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{}}}`, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/15/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{}}}`,
}, },
{ {
subtest: "Patroni configured", subtest: "Patroni configured",
pgParam: &acidv1.PostgresqlParam{PgVersion: "11"}, pgParam: &acidv1.PostgresqlParam{PgVersion: "15"},
patroni: &acidv1.Patroni{ patroni: &acidv1.Patroni{
InitDB: map[string]string{ InitDB: map[string]string{
"encoding": "UTF8", "encoding": "UTF8",
@ -108,11 +108,11 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
PamRoleName: "zalandos", PamRoleName: "zalandos",
}, },
}, },
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/11/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"synchronous_node_count":1,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}},"failsafe_mode":true}}}`, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/15/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"synchronous_node_count":1,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}},"failsafe_mode":true}}}`,
}, },
{ {
subtest: "Patroni failsafe_mode configured globally", subtest: "Patroni failsafe_mode configured globally",
pgParam: &acidv1.PostgresqlParam{PgVersion: "14"}, pgParam: &acidv1.PostgresqlParam{PgVersion: "15"},
patroni: &acidv1.Patroni{}, patroni: &acidv1.Patroni{},
opConfig: &config.Config{ opConfig: &config.Config{
Auth: config.Auth{ Auth: config.Auth{
@ -120,11 +120,11 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
}, },
EnablePatroniFailsafeMode: util.True(), EnablePatroniFailsafeMode: util.True(),
}, },
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/14/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":true}}}`, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/15/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":true}}}`,
}, },
{ {
subtest: "Patroni failsafe_mode configured globally, disabled for cluster", subtest: "Patroni failsafe_mode configured globally, disabled for cluster",
pgParam: &acidv1.PostgresqlParam{PgVersion: "14"}, pgParam: &acidv1.PostgresqlParam{PgVersion: "15"},
patroni: &acidv1.Patroni{ patroni: &acidv1.Patroni{
FailsafeMode: util.False(), FailsafeMode: util.False(),
}, },
@ -134,11 +134,11 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
}, },
EnablePatroniFailsafeMode: util.True(), EnablePatroniFailsafeMode: util.True(),
}, },
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/14/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":false}}}`, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/15/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":false}}}`,
}, },
{ {
subtest: "Patroni failsafe_mode disabled globally, configured for cluster", subtest: "Patroni failsafe_mode disabled globally, configured for cluster",
pgParam: &acidv1.PostgresqlParam{PgVersion: "14"}, pgParam: &acidv1.PostgresqlParam{PgVersion: "15"},
patroni: &acidv1.Patroni{ patroni: &acidv1.Patroni{
FailsafeMode: util.True(), FailsafeMode: util.True(),
}, },
@ -148,7 +148,7 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
}, },
EnablePatroniFailsafeMode: util.False(), EnablePatroniFailsafeMode: util.False(),
}, },
result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/14/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":true}}}`, result: `{"postgresql":{"bin_dir":"/usr/lib/postgresql/15/bin"},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"failsafe_mode":true}}}`,
}, },
} }
for _, tt := range tests { for _, tt := range tests {
@ -180,15 +180,15 @@ func TestExtractPgVersionFromBinPath(t *testing.T) {
}, },
{ {
subTest: "test current bin path against hard coded template", subTest: "test current bin path against hard coded template",
binPath: "/usr/lib/postgresql/12/bin", binPath: "/usr/lib/postgresql/15/bin",
template: pgBinariesLocationTemplate, template: pgBinariesLocationTemplate,
expected: "12", expected: "15",
}, },
{ {
subTest: "test alternative bin path against a matching template", subTest: "test alternative bin path against a matching template",
binPath: "/usr/pgsql-12/bin", binPath: "/usr/pgsql-15/bin",
template: "/usr/pgsql-%v/bin", template: "/usr/pgsql-%v/bin",
expected: "12", expected: "15",
}, },
} }
@ -1849,7 +1849,7 @@ func TestSidecars(t *testing.T) {
spec = acidv1.PostgresSpec{ spec = acidv1.PostgresSpec{
PostgresqlParam: acidv1.PostgresqlParam{ PostgresqlParam: acidv1.PostgresqlParam{
PgVersion: "12.1", PgVersion: "15",
Parameters: map[string]string{ Parameters: map[string]string{
"max_connections": "100", "max_connections": "100",
}, },

View File

@ -11,13 +11,12 @@ import (
// VersionMap Map of version numbers // VersionMap Map of version numbers
var VersionMap = map[string]int{ var VersionMap = map[string]int{
"9.5": 90500, "10": 100000,
"9.6": 90600, "11": 110000,
"10": 100000, "12": 120000,
"11": 110000, "13": 130000,
"12": 120000, "14": 140000,
"13": 130000, "15": 150000,
"14": 140000,
} }
// IsBiggerPostgresVersion Compare two Postgres version numbers // IsBiggerPostgresVersion Compare two Postgres version numbers
@ -36,7 +35,7 @@ func (c *Cluster) GetDesiredMajorVersionAsInt() int {
func (c *Cluster) GetDesiredMajorVersion() string { func (c *Cluster) GetDesiredMajorVersion() string {
if c.Config.OpConfig.MajorVersionUpgradeMode == "full" { if c.Config.OpConfig.MajorVersionUpgradeMode == "full" {
// e.g. current is 9.6, minimal is 11 allowing 11 to 14 clusters, everything below is upgraded // e.g. current is 10, minimal is 11 allowing 11 to 14 clusters, everything below is upgraded
if IsBiggerPostgresVersion(c.Spec.PgVersion, c.Config.OpConfig.MinimalMajorVersion) { if IsBiggerPostgresVersion(c.Spec.PgVersion, c.Config.OpConfig.MinimalMajorVersion) {
c.logger.Infof("overwriting configured major version %s to %s", c.Spec.PgVersion, c.Config.OpConfig.TargetMajorVersion) c.logger.Infof("overwriting configured major version %s to %s", c.Spec.PgVersion, c.Config.OpConfig.TargetMajorVersion)
return c.Config.OpConfig.TargetMajorVersion return c.Config.OpConfig.TargetMajorVersion

View File

@ -62,7 +62,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
// major version upgrade config // major version upgrade config
result.MajorVersionUpgradeMode = util.Coalesce(fromCRD.MajorVersionUpgrade.MajorVersionUpgradeMode, "off") result.MajorVersionUpgradeMode = util.Coalesce(fromCRD.MajorVersionUpgrade.MajorVersionUpgradeMode, "off")
result.MajorVersionUpgradeTeamAllowList = fromCRD.MajorVersionUpgrade.MajorVersionUpgradeTeamAllowList result.MajorVersionUpgradeTeamAllowList = fromCRD.MajorVersionUpgrade.MajorVersionUpgradeTeamAllowList
result.MinimalMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.MinimalMajorVersion, "9.6") result.MinimalMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.MinimalMajorVersion, "11")
result.TargetMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.TargetMajorVersion, "14") result.TargetMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.TargetMajorVersion, "14")
// kubernetes config // kubernetes config

View File

@ -230,7 +230,7 @@ type Config struct {
EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"` EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"`
MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"` MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"`
MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""` MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""`
MinimalMajorVersion string `name:"minimal_major_version" default:"9.6"` MinimalMajorVersion string `name:"minimal_major_version" default:"11"`
TargetMajorVersion string `name:"target_major_version" default:"14"` TargetMajorVersion string `name:"target_major_version" default:"14"`
PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"` PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"`
PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"` PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"`

View File

@ -72,6 +72,7 @@ spec:
"limit_iops": 16000, "limit_iops": 16000,
"limit_throughput": 1000, "limit_throughput": 1000,
"postgresql_versions": [ "postgresql_versions": [
"15",
"14", "14",
"13", "13",
"12", "12",

View File

@ -321,7 +321,7 @@ DEFAULT_UI_CONFIG = {
'users_visible': True, 'users_visible': True,
'databases_visible': True, 'databases_visible': True,
'resources_visible': RESOURCES_VISIBLE, 'resources_visible': RESOURCES_VISIBLE,
'postgresql_versions': ['11','12','13','14'], 'postgresql_versions': ['11', '12', '13', '14'],
'dns_format_string': '{0}.{1}', 'dns_format_string': '{0}.{1}',
'pgui_link': '', 'pgui_link': '',
'static_network_whitelist': {}, 'static_network_whitelist': {},

View File

@ -308,7 +308,7 @@ def read_versions(
if uid == 'wal' or defaulting(lambda: UUID(uid)) if uid == 'wal' or defaulting(lambda: UUID(uid))
] ]
BACKUP_VERSION_PREFIXES = ['', '9.5/', '9.6/', '10/', '11/', '12/', '13/', '14/'] BACKUP_VERSION_PREFIXES = ['', '9.6/', '10/', '11/', '12/', '13/', '14/', '15/']
def read_basebackups( def read_basebackups(
pg_cluster, pg_cluster,

View File

@ -25,6 +25,7 @@ default_operator_ui_config='{
"cost_core": 0.0575, "cost_core": 0.0575,
"cost_memory": 0.014375, "cost_memory": 0.014375,
"postgresql_versions": [ "postgresql_versions": [
"15",
"14", "14",
"13", "13",
"12", "12",